From cacf818ce55804b7449ba63ad39ea0e6a3d9eb85 Mon Sep 17 00:00:00 2001 From: TheHamkerCat Date: Thu, 28 Nov 2024 02:42:21 +0530 Subject: [PATCH] feat: extend smart search, match exif-description too --- server/src/interfaces/search.interface.ts | 5 +++ server/src/repositories/search.repository.ts | 43 ++++++++++++++++---- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/server/src/interfaces/search.interface.ts b/server/src/interfaces/search.interface.ts index 87bf1bc4b1..0a84929f8d 100644 --- a/server/src/interfaces/search.interface.ts +++ b/server/src/interfaces/search.interface.ts @@ -104,6 +104,10 @@ export interface SearchExifOptions { state?: string | null; } +export interface SearchTextOptions { + query?: string; +} + export interface SearchEmbeddingOptions { embedding: number[]; userIds: string[]; @@ -140,6 +144,7 @@ export type AssetSearchBuilderOptions = Omit { let results: PaginationResult = { items: [], hasNextPage: false }; await this.assetRepository.manager.transaction(async (manager) => { - let builder = manager.createQueryBuilder(AssetEntity, 'asset'); + let builder = manager.createQueryBuilder(AssetEntity, 'asset') + .leftJoinAndSelect('asset.exifInfo', 'exif'); builder = searchAssetBuilder(builder, options); - builder - .innerJoin('asset.smartSearch', 'search') - .andWhere('asset.ownerId IN (:...userIds )') - .orderBy('search.embedding <=> :embedding') - .setParameters({ userIds, embedding: asVector(embedding) }); + builder.andWhere('asset.ownerId IN (:...userIds)'); + + const parameters: Record = { userIds }; + + if (embedding) { + builder + .innerJoin('asset.smartSearch', 'search') + .addSelect('search.embedding <=> :embedding', 'similarity'); + parameters.embedding = asVector(embedding); + } + + if (query) { + parameters.query = query; + } + + if (query && embedding) { + builder.orderBy(` + CASE WHEN to_tsvector('english', COALESCE(exif.description, '')) @@ plainto_tsquery('english', :query) + THEN + ts_rank( + to_tsvector('english', COALESCE(exif.description, '')), + plainto_tsquery('english', :query) + ) + ELSE 0 END * 0.7 + + COALESCE((1 - (search.embedding <=> :embedding)), 0) * 0.3 + `, 'DESC'); + } else if (embedding) { + builder.orderBy('search.embedding <=> :embedding', 'ASC'); + } + + builder.setParameters(parameters); const runtimeConfig = this.getRuntimeConfig(pagination.size); if (runtimeConfig) { await manager.query(runtimeConfig); } + results = await paginatedBuilder(builder, { mode: PaginationMode.LIMIT_OFFSET, skip: (pagination.page - 1) * pagination.size,