From c1175be1d040b6af0161a0c52126256991ac9078 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Tue, 21 Nov 2023 01:52:30 -0500 Subject: [PATCH] face optimizations --- server/src/infra/entities/asset-face.entity.ts | 2 +- server/src/infra/entities/smart-search.entity.ts | 1 + server/src/infra/repositories/person.repository.ts | 14 +++++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/server/src/infra/entities/asset-face.entity.ts b/server/src/infra/entities/asset-face.entity.ts index 4c0f75102..363e3838e 100644 --- a/server/src/infra/entities/asset-face.entity.ts +++ b/server/src/infra/entities/asset-face.entity.ts @@ -14,7 +14,7 @@ export class AssetFaceEntity { @Column({ nullable: true, type: 'uuid' }) personId!: string | null; - @Column({ type: 'float4', array: true }) + @Column({ type: 'float4', array: true, select: false }) embedding!: number[]; @Column({ default: 0, type: 'int' }) diff --git a/server/src/infra/entities/smart-search.entity.ts b/server/src/infra/entities/smart-search.entity.ts index bd9721441..7c8e9ca43 100644 --- a/server/src/infra/entities/smart-search.entity.ts +++ b/server/src/infra/entities/smart-search.entity.ts @@ -13,6 +13,7 @@ export class SmartSearchEntity { @Column({ type: 'float4', array: true, + select: false, }) embedding!: number[]; } diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/infra/repositories/person.repository.ts index 701396792..50f689ae1 100644 --- a/server/src/infra/repositories/person.repository.ts +++ b/server/src/infra/repositories/person.repository.ts @@ -15,11 +15,17 @@ import { asVector } from '../infra.utils'; import { dataSource } from '..'; export class PersonRepository implements IPersonRepository { + private readonly faceColumns: string[]; constructor( @InjectRepository(AssetEntity) private assetRepository: Repository, @InjectRepository(PersonEntity) private personRepository: Repository, @InjectRepository(AssetFaceEntity) private assetFaceRepository: Repository, - ) {} + ) { + this.faceColumns = this.assetFaceRepository.manager.connection + .getMetadata(AssetFaceEntity).ownColumns + .map((column) => column.propertyName) + .filter((propertyName) => propertyName !== 'embedding'); + } /** * Before reassigning faces, delete potential key violations @@ -245,12 +251,14 @@ export class PersonRepository implements IPersonRepository { async searchByEmbedding({ ownerId, embedding, numResults, maxDistance }: EmbeddingSearch): Promise { const cte = this.assetFaceRepository.createQueryBuilder('faces') .select('1 + (faces.embedding <=> :embedding)', 'distance') - .leftJoinAndSelect('faces.asset', 'asset') + .innerJoin('faces.asset', 'asset') .where('asset.ownerId = :ownerId') .orderBy(`faces.embedding <=> :embedding`) .setParameters({ownerId, embedding: asVector(embedding)}) .limit(numResults); - + + this.faceColumns.forEach((col) => cte.addSelect(`faces.${col} AS "${col}"`)); + const res = await dataSource.createQueryBuilder() .select('res.*') .addCommonTableExpression(cte, 'cte')