mirror of
https://github.com/immich-app/immich.git
synced 2025-12-21 01:11:16 +03:00
feat(server): separate face search relation (#10371)
* wip * various fixes * new migration * fix test * add face search entity, update sql * update e2e * set storage to external
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { FaceSearchEntity } from 'src/entities/face-search.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, ManyToOne, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
@Entity('asset_faces', { synchronize: false })
|
||||
@Index('IDX_asset_faces_assetId_personId', ['assetId', 'personId'])
|
||||
@@ -15,9 +16,8 @@ export class AssetFaceEntity {
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
personId!: string | null;
|
||||
|
||||
@Index('face_index', { synchronize: false })
|
||||
@Column({ type: 'float4', array: true, select: false, transformer: { from: (v) => JSON.parse(v), to: (v) => v } })
|
||||
embedding!: number[];
|
||||
@OneToOne(() => FaceSearchEntity, (faceSearchEntity) => faceSearchEntity.face, { cascade: ['insert'] })
|
||||
faceSearch?: FaceSearchEntity;
|
||||
|
||||
@Column({ default: 0, type: 'int' })
|
||||
imageWidth!: number;
|
||||
|
||||
21
server/src/entities/face-search.entity.ts
Normal file
21
server/src/entities/face-search.entity.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { asVector } from 'src/utils/database';
|
||||
import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity('face_search', { synchronize: false })
|
||||
export class FaceSearchEntity {
|
||||
@OneToOne(() => AssetFaceEntity, { onDelete: 'CASCADE', nullable: true })
|
||||
@JoinColumn({ name: 'faceId', referencedColumnName: 'id' })
|
||||
face?: AssetFaceEntity;
|
||||
|
||||
@PrimaryColumn()
|
||||
faceId!: string;
|
||||
|
||||
@Index('face_index', { synchronize: false })
|
||||
@Column({
|
||||
type: 'float4',
|
||||
array: true,
|
||||
transformer: { from: (v) => JSON.parse(v), to: (v) => asVector(v) },
|
||||
})
|
||||
embedding!: number[];
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { AssetStackEntity } from 'src/entities/asset-stack.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { AuditEntity } from 'src/entities/audit.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { FaceSearchEntity } from 'src/entities/face-search.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { LibraryEntity } from 'src/entities/library.entity';
|
||||
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||
@@ -34,6 +35,7 @@ export const entities = [
|
||||
AssetJobStatusEntity,
|
||||
AuditEntity,
|
||||
ExifEntity,
|
||||
FaceSearchEntity,
|
||||
GeodataPlacesEntity,
|
||||
MemoryEntity,
|
||||
MoveEntity,
|
||||
|
||||
Reference in New Issue
Block a user