Use single query for tag previews

cache
Varun Patil 2022-10-07 19:09:05 -07:00
parent 991515e9e5
commit d40217604e
3 changed files with 42 additions and 12 deletions

View File

@ -321,10 +321,27 @@ class ApiController extends Controller {
); );
// Preload all tag previews // Preload all tag previews
$previews = $this->timelineQuery->getTagPreviews($folder);
// Convert to map with key as systemtagid
$previews_map = [];
foreach ($previews as &$preview) {
$key = $preview["systemtagid"];
if (!array_key_exists($key, $previews_map)) {
$previews_map[$key] = [];
}
unset($preview["systemtagid"]);
$previews_map[$key][] = $preview;
}
// Add previews to list
foreach ($list as &$tag) { foreach ($list as &$tag) {
$tag["previews"] = $this->timelineQuery->getTagPreviews( $key = $tag["id"];
$folder, $tag["id"], if (array_key_exists($key, $previews_map)) {
); $tag["previews"] = $previews_map[$key];
} else {
$tag["previews"] = [];
}
} }
return new JSONResponse($list, Http::STATUS_OK); return new JSONResponse($list, Http::STATUS_OK);

View File

@ -56,6 +56,7 @@ trait TimelineQueryFaces {
public function getFacePreviews(Folder $folder) { public function getFacePreviews(Folder $folder) {
$query = $this->connection->getQueryBuilder(); $query = $this->connection->getQueryBuilder();
// Windowing
$rowNumber = $query->createFunction('ROW_NUMBER() OVER (PARTITION BY rfd.cluster_id) as n'); $rowNumber = $query->createFunction('ROW_NUMBER() OVER (PARTITION BY rfd.cluster_id) as n');
// SELECT face detections for ID // SELECT face detections for ID

View File

@ -69,14 +69,17 @@ trait TimelineQueryTags {
return $tags; return $tags;
} }
public function getTagPreviews(Folder $folder, int $tagId) { public function getTagPreviews(Folder $folder) {
$query = $this->connection->getQueryBuilder(); $query = $this->connection->getQueryBuilder();
// Windowing
$rowNumber = $query->createFunction('ROW_NUMBER() OVER (PARTITION BY stom.systemtagid) as n');
// SELECT all photos with this tag // SELECT all photos with this tag
$query->select('f.fileid', 'f.etag')->from('systemtag_object_mapping', 'stom')->where($query->expr()->andX( $query->select('f.fileid', 'f.etag', 'stom.systemtagid', $rowNumber)->from(
$query->expr()->eq('stom.objecttype', $query->createNamedParameter("files")), 'systemtag_object_mapping', 'stom')->where(
$query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tagId, IQueryBuilder::PARAM_INT)), $query->expr()->eq('stom.objecttype', $query->createNamedParameter("files")),
)); );
// WHERE these items are memories indexed photos // WHERE these items are memories indexed photos
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid')); $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid'));
@ -84,15 +87,24 @@ trait TimelineQueryTags {
// WHERE these photos are in the user's requested folder recursively // WHERE these photos are in the user's requested folder recursively
$query->innerJoin('m', 'filecache', 'f', $this->getFilecacheJoinQuery($query, $folder, true, false)); $query->innerJoin('m', 'filecache', 'f', $this->getFilecacheJoinQuery($query, $folder, true, false));
// MAX 4 results // Make this a sub query
$query->setMaxResults(4); $fun = $query->createFunction('(' . $query->getSQL() . ')');
// FETCH all previews // Create outer query
$previews = $query->executeQuery()->fetchAll(); $outerQuery = $this->connection->getQueryBuilder();
$outerQuery->setParameters($query->getParameters());
$outerQuery->select('*')->from($fun, 't');
$outerQuery->where($query->expr()->lte('t.n', $outerQuery->createParameter('nc')));
$outerQuery->setParameter('nc', 4, IQueryBuilder::PARAM_INT);
// FETCH all tag previews
$previews = $outerQuery->executeQuery()->fetchAll();
// Post-process // Post-process
foreach($previews as &$row) { foreach($previews as &$row) {
$row["fileid"] = intval($row["fileid"]); $row["fileid"] = intval($row["fileid"]);
$row["systemtagid"] = intval($row["systemtagid"]);
unset($row["n"]);
} }
return $previews; return $previews;