days: improve monthView query

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/877/head
Varun Patil 2023-10-14 16:35:06 -07:00
parent 568e10d999
commit 2d5b687350
2 changed files with 47 additions and 24 deletions

View File

@ -70,35 +70,18 @@ class DaysController extends GenericApiController
{ {
return Util::guardEx(function () use ($id) { return Util::guardEx(function () use ($id) {
// Split at commas and convert all parts to int // Split at commas and convert all parts to int
/** @var int[] */
$dayIds = array_map(static fn ($p) => (int) $p, explode(',', $id)); $dayIds = array_map(static fn ($p) => (int) $p, explode(',', $id));
// Check if $dayIds is empty
if (empty($dayIds)) {
return new JSONResponse([], Http::STATUS_OK);
}
// Convert to actual dayIds if month view
if ($this->isMonthView()) {
$dayIds = $this->monthIdToDayIds($dayIds[0]);
}
// Run actual query // Run actual query
$list = $this->tq->getDay( $list = $this->tq->getDay(
$dayIds, $dayIds,
$this->isRecursive(), $this->isRecursive(),
$this->isArchive(), $this->isArchive(),
$this->isHidden(), $this->isHidden(),
$this->isMonthView(),
$this->getTransformations(), $this->getTransformations(),
); );
// Force month id for dayId for month view
if ($this->isMonthView()) {
foreach ($list as &$photo) {
$photo['dayid'] = $dayIds[0];
}
}
// Reverse response if requested. // Reverse response if requested.
if ($this->isReverse()) { if ($this->isReverse()) {
$list = array_reverse($list); $list = array_reverse($list);
@ -203,6 +186,7 @@ class DaysController extends GenericApiController
$this->isRecursive(), $this->isRecursive(),
$this->isArchive(), $this->isArchive(),
$this->isHidden(), $this->isHidden(),
$this->isMonthView(),
$this->getTransformations(), $this->getTransformations(),
); );

View File

@ -57,21 +57,29 @@ trait TimelineQueryDays
/** /**
* Get the day response from the database for the timeline. * Get the day response from the database for the timeline.
* *
* @param int[] $day_ids The day ids to fetch * @param int[] $dayIds The day ids to fetch
* @param bool $recursive If the query should be recursive * @param bool $recursive If the query should be recursive
* @param bool $archive If the query should include only the archive folder * @param bool $archive If the query should include only the archive folder
* @param bool $hidden If the query should include hidden files * @param bool $hidden If the query should include hidden files
* @param bool $monthView If the query should be in month view (dayIds are monthIds)
* @param array $queryTransforms The query transformations to apply * @param array $queryTransforms The query transformations to apply
* *
* @return array An array of day responses * @return array An array of day responses
*/ */
public function getDay( public function getDay(
array $day_ids, array $dayIds,
bool $recursive, bool $recursive,
bool $archive, bool $archive,
bool $hidden, bool $hidden,
bool $monthView,
array $queryTransforms = [] array $queryTransforms = []
): array { ): array {
// Check if we have any dayIds
if (empty($dayIds)) {
return [];
}
// Make new query
$query = $this->connection->getQueryBuilder(); $query = $this->connection->getQueryBuilder();
// Get all entries also present in filecache // Get all entries also present in filecache
@ -92,8 +100,16 @@ trait TimelineQueryDays
// JOIN with mimetypes to get the mimetype // JOIN with mimetypes to get the mimetype
$query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id')); $query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id'));
// Filter by dayid if ($monthView) {
$query->andWhere($query->expr()->in('m.dayid', $query->createNamedParameter($day_ids, IQueryBuilder::PARAM_INT_ARRAY))); // Convert monthIds to dayIds
$query->andWhere($query->expr()->orX(...array_map(fn ($monthId) => $query->expr()->andX(
$query->expr()->gte('m.dayid', $query->createNamedParameter($monthId, IQueryBuilder::PARAM_INT)),
$query->expr()->lte('m.dayid', $query->createNamedParameter($this->monthEndDayId($monthId), IQueryBuilder::PARAM_INT))
), $dayIds)));
} else {
// Filter by list of dayIds
$query->andWhere($query->expr()->in('m.dayid', $query->createNamedParameter($dayIds, IQueryBuilder::PARAM_INT_ARRAY)));
}
// Add favorite field // Add favorite field
$this->addFavoriteTag($query); $this->addFavoriteTag($query);
@ -113,7 +129,7 @@ trait TimelineQueryDays
// Post process the day in-place // Post process the day in-place
foreach ($day as &$photo) { foreach ($day as &$photo) {
$this->processDayPhoto($photo); $this->processDayPhoto($photo, $monthView);
} }
return $day; return $day;
@ -218,8 +234,11 @@ trait TimelineQueryDays
/** /**
* Process the single day response. * Process the single day response.
*
* @param array $row The day response
* @param bool $monthView Whether the response is in month view
*/ */
private function processDayPhoto(array &$row): void private function processDayPhoto(array &$row, bool $monthView = false): void
{ {
// Convert field types // Convert field types
$row['fileid'] = (int) $row['fileid']; $row['fileid'] = (int) $row['fileid'];
@ -263,6 +282,11 @@ trait TimelineQueryDays
$row['auid'] = Exif::getAUID($epoch, $size); $row['auid'] = Exif::getAUID($epoch, $size);
unset($row['size']); unset($row['size']);
} }
// Convert dayId to monthId if needed
if ($monthView) {
$row['dayid'] = $this->dayIdToMonthId($row['dayid']);
}
} }
/** /**
@ -285,4 +309,19 @@ trait TimelineQueryDays
$query->setParameter('cteIncludeHidden', true, IQueryBuilder::PARAM_BOOL); $query->setParameter('cteIncludeHidden', true, IQueryBuilder::PARAM_BOOL);
} }
} }
private function monthEndDayId(int $monthId): int
{
return (int) (strtotime(date('Ymt', $monthId * 86400)) / 86400);
}
private function dayIdToMonthId(int $dayId): int
{
static $memoize = [];
if (\array_key_exists($dayId, $memoize)) {
return $memoize[$dayId];
}
return $memoize[$dayId] = strtotime(date('Ym', $dayId * 86400).'01') / 86400;
}
} }