1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-12-16 00:11:21 +02:00

Make autocomplete projected #1015

This commit is contained in:
Patrik J. Braun
2025-09-07 15:02:01 +02:00
parent 9b0411d011
commit db8878511d
7 changed files with 922 additions and 816 deletions

View File

@@ -6,6 +6,7 @@ export class SessionContext {
user: ContextUser;
// New structured projection with prebuilt SQL and params
projectionQuery?: Brackets;
hasDirectoryProjection: boolean;
}
export interface ContextUser extends UserDTO {

View File

@@ -355,11 +355,11 @@ export class GalleryManager {
.where('directory.id = :id', {
id: partialDirId
})
.leftJoinAndSelect('directory.directories', 'directories')
.leftJoinAndSelect('directory.cache', 'cache', 'cache.projectionKey = :pk AND cache.valid = 1', {pk: session.user.projectionKey})
.leftJoinAndSelect('cache.cover', 'cover')
.leftJoinAndSelect('cover.directory', 'coverDirectory')
.leftJoinAndSelect('directory.directories', 'directories')
.leftJoinAndSelect('directories.cache', 'dcache', 'dcache.projectionKey = :pk AND dcache.valid = 1', {pk: session.user.projectionKey})
.leftJoinAndSelect('dcache.cover', 'dcover')
.leftJoinAndSelect('dcover.directory', 'dcoverDirectory')

View File

@@ -141,7 +141,7 @@ export class ProjectedCacheManager implements IObjectManager {
.innerJoin('media.directory', 'directory')
.where('directory.id = :dir', {dir: dir.id});
if (session?.projectionQuery) {
if (session.projectionQuery) {
baseQb.andWhere(session.projectionQuery);
}
@@ -174,7 +174,7 @@ export class ProjectedCacheManager implements IObjectManager {
})
);
if (session?.projectionQuery) {
if (session.projectionQuery) {
recQb.andWhere(session.projectionQuery);
}
const aggRec = await recQb.select(['COUNT(*) as cnt']).getRawOne();

View File

@@ -88,9 +88,14 @@ export class SearchManager {
.where('media.metadata.keywords LIKE :textKW COLLATE ' + SQL_COLLATE, {
textKW: '%' + text + '%',
});
if (session.projectionQuery) {
if (session.hasDirectoryProjection) {
q.leftJoin('media.directory', 'directory');
}
q.andWhere(session.projectionQuery);
}
q.limit(Config.Search.AutoComplete.ItemsPerCategory.keyword);
(await q.getRawMany())
.map(
@@ -163,7 +168,11 @@ export class SearchManager {
);
});
q.where(b);
if (session.projectionQuery) {
if (session.hasDirectoryProjection) {
q.leftJoin('media.directory', 'directory');
}
q.andWhere(session.projectionQuery);
}
@@ -207,7 +216,11 @@ export class SearchManager {
text: '%' + text + '%',
});
if (session.projectionQuery) {
if (session.hasDirectoryProjection) {
q.leftJoin('media.directory', 'directory');
}
q.andWhere(session.projectionQuery);
}
q.limit(
@@ -236,6 +249,9 @@ export class SearchManager {
);
if (session.projectionQuery) {
if (session.hasDirectoryProjection) {
q.leftJoin('media.directory', 'directory');
}
q.andWhere(session.projectionQuery);
}
q.limit(
@@ -255,20 +271,26 @@ export class SearchManager {
type === SearchQueryTypes.any_text ||
type === SearchQueryTypes.directory
) {
partialResult.push(
this.encapsulateAutoComplete(
(
await directoryRepository
.createQueryBuilder('dir')
.select('DISTINCT(dir.name)')
.where('dir.name LIKE :text COLLATE ' + SQL_COLLATE, {
const dirs = await directoryRepository
.createQueryBuilder('directory')
.leftJoinAndSelect('directory.cache', 'cache', 'cache.projectionKey = :pk AND cache.valid = 1', {pk: session.user.projectionKey})
.where('directory.name LIKE :text COLLATE ' + SQL_COLLATE, {
text: '%' + text + '%',
})
.andWhere('(cache.recursiveMediaCount > 0 OR cache.id is NULL)')
.limit(
Config.Search.AutoComplete.ItemsPerCategory.directory
)
.getRawMany()
).map((r) => r.name),
.getMany();
// fill cache as we need it for this autocomplete search
for (const dir of dirs) {
if (!dir.cache?.valid) {
dir.cache = await ObjectManagers.getInstance().ProjectedCacheManager.setAndGetCacheForDirectory(connection, session, dir);
}
}
partialResult.push(
this.encapsulateAutoComplete(
dirs.filter(d => d.cache.valid && d.cache.recursiveMediaCount > 0).map((r) => r.name),
SearchQueryTypes.directory
)
);
@@ -1274,8 +1296,22 @@ export class SearchManager {
return queryIN;
}
public hasDirectoryQuery(query: SearchQueryDTO): boolean {
switch (query.type) {
case SearchQueryTypes.AND:
case SearchQueryTypes.OR:
case SearchQueryTypes.SOME_OF:
return (query as SearchListQuery).list.some(q => this.hasDirectoryQuery(q));
case SearchQueryTypes.any_text:
case SearchQueryTypes.directory:
return true;
}
return false;
}
/**
* Returns only those part of a query tree that only contains directory related search queries
* Returns only those parts of a query tree that only contains directory-related search queries
*/
private filterDirectoryQuery(query: SearchQueryDTO): SearchQueryDTO {
switch (query.type) {

View File

@@ -67,6 +67,7 @@ export class SessionManager {
if (finalQuery) {
// Build the Brackets-based query
context.projectionQuery = await ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(finalQuery);
context.hasDirectoryProjection = ObjectManagers.getInstance().SearchManager.hasDirectoryQuery(finalQuery);
context.user.projectionKey = this.createProjectionKey(finalQuery);
if (SearchQueryUtils.isQueryEmpty(finalQuery)) {
Logger.silly(LOG_TAG, 'Empty Projection query.');

View File

@@ -43,7 +43,7 @@ class GalleryManagerTest extends GalleryManager {
}
const LOG_TAG = 'DBTestHelper';
const LOG_TAG = '[DBTestHelper]';
export class DBTestHelper {

File diff suppressed because it is too large Load Diff