|
|
|
|
@ -9,13 +9,14 @@ import { PersonEntity } from 'src/entities/person.entity';
|
|
|
|
|
import { PaginationMode, SourceType } from 'src/enum';
|
|
|
|
|
import {
|
|
|
|
|
AssetFaceId,
|
|
|
|
|
DeleteAllFacesOptions,
|
|
|
|
|
DeleteFacesOptions,
|
|
|
|
|
IPersonRepository,
|
|
|
|
|
PeopleStatistics,
|
|
|
|
|
PersonNameResponse,
|
|
|
|
|
PersonNameSearchOptions,
|
|
|
|
|
PersonSearchOptions,
|
|
|
|
|
PersonStatistics,
|
|
|
|
|
UnassignFacesOptions,
|
|
|
|
|
UpdateFacesData,
|
|
|
|
|
} from 'src/interfaces/person.interface';
|
|
|
|
|
import { Instrumentation } from 'src/utils/instrumentation';
|
|
|
|
|
@ -39,12 +40,23 @@ export class PersonRepository implements IPersonRepository {
|
|
|
|
|
.createQueryBuilder()
|
|
|
|
|
.update()
|
|
|
|
|
.set({ personId: newPersonId })
|
|
|
|
|
.where(_.omitBy({ personId: oldPersonId ?? undefined, id: faceIds ? In(faceIds) : undefined }, _.isUndefined))
|
|
|
|
|
.where(_.omitBy({ personId: oldPersonId, id: faceIds ? In(faceIds) : undefined }, _.isUndefined))
|
|
|
|
|
.execute();
|
|
|
|
|
|
|
|
|
|
return result.affected ?? 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async unassignFaces({ sourceType }: UnassignFacesOptions): Promise<void> {
|
|
|
|
|
await this.assetFaceRepository
|
|
|
|
|
.createQueryBuilder()
|
|
|
|
|
.update()
|
|
|
|
|
.set({ personId: null })
|
|
|
|
|
.where({ sourceType })
|
|
|
|
|
.execute();
|
|
|
|
|
|
|
|
|
|
await this.vacuum({ reindexVectors: false });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async delete(entities: PersonEntity[]): Promise<void> {
|
|
|
|
|
await this.personRepository.remove(entities);
|
|
|
|
|
}
|
|
|
|
|
@ -53,21 +65,14 @@ export class PersonRepository implements IPersonRepository {
|
|
|
|
|
await this.personRepository.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async deleteAllFaces({ sourceType }: DeleteAllFacesOptions): Promise<void> {
|
|
|
|
|
if (!sourceType) {
|
|
|
|
|
return this.assetFaceRepository.query('TRUNCATE TABLE asset_faces CASCADE');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async deleteFaces({ sourceType }: DeleteFacesOptions): Promise<void> {
|
|
|
|
|
await this.assetFaceRepository
|
|
|
|
|
.createQueryBuilder('asset_faces')
|
|
|
|
|
.delete()
|
|
|
|
|
.andWhere('sourceType = :sourceType', { sourceType })
|
|
|
|
|
.execute();
|
|
|
|
|
|
|
|
|
|
await this.assetFaceRepository.query('VACUUM ANALYZE asset_faces, face_search');
|
|
|
|
|
if (sourceType === SourceType.MACHINE_LEARNING) {
|
|
|
|
|
await this.assetFaceRepository.query('REINDEX INDEX face_index');
|
|
|
|
|
}
|
|
|
|
|
await this.vacuum({ reindexVectors: sourceType === SourceType.MACHINE_LEARNING });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getAllFaces(
|
|
|
|
|
@ -331,4 +336,13 @@ export class PersonRepository implements IPersonRepository {
|
|
|
|
|
const { id } = await this.personRepository.save(person);
|
|
|
|
|
return this.personRepository.findOneByOrFail({ id });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async vacuum({ reindexVectors }: { reindexVectors: boolean }): Promise<void> {
|
|
|
|
|
await this.assetFaceRepository.query('VACUUM ANALYZE asset_faces, face_search, person');
|
|
|
|
|
await this.assetFaceRepository.query('REINDEX TABLE asset_faces');
|
|
|
|
|
await this.assetFaceRepository.query('REINDEX TABLE person');
|
|
|
|
|
if (reindexVectors) {
|
|
|
|
|
await this.assetFaceRepository.query('REINDEX TABLE face_search');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|