浏览代码

fix(server): people sorting (#3713)

martin 1 年之前
父节点
当前提交
c27c12d975

+ 1 - 0
server/src/domain/person/person.repository.ts

@@ -4,6 +4,7 @@ export const IPersonRepository = 'IPersonRepository';
 
 export interface PersonSearchOptions {
   minimumFaceCount: number;
+  withHidden: boolean;
 }
 
 export interface UpdateFacesData {

+ 3 - 3
server/src/domain/person/person.service.spec.ts

@@ -47,7 +47,7 @@ describe(PersonService.name, () => {
         visible: 1,
         people: [responseDto],
       });
-      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1 });
+      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1, withHidden: false });
     });
     it('should get all visible people with thumbnails', async () => {
       personMock.getAll.mockResolvedValue([personStub.withName, personStub.hidden]);
@@ -56,7 +56,7 @@ describe(PersonService.name, () => {
         visible: 1,
         people: [responseDto],
       });
-      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1 });
+      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1, withHidden: false });
     });
     it('should get all hidden and visible people with thumbnails', async () => {
       personMock.getAll.mockResolvedValue([personStub.withName, personStub.hidden]);
@@ -73,7 +73,7 @@ describe(PersonService.name, () => {
           },
         ],
       });
-      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1 });
+      expect(personMock.getAll).toHaveBeenCalledWith(authStub.admin.id, { minimumFaceCount: 1, withHidden: true });
     });
   });
 

+ 4 - 2
server/src/domain/person/person.service.ts

@@ -26,8 +26,10 @@ export class PersonService {
   ) {}
 
   async getAll(authUser: AuthUserDto, dto: PersonSearchDto): Promise<PeopleResponseDto> {
-    const people = await this.repository.getAll(authUser.id, { minimumFaceCount: 1 });
-
+    const people = await this.repository.getAll(authUser.id, {
+      minimumFaceCount: 1,
+      withHidden: dto.withHidden || false,
+    });
     const persons: PersonResponseDto[] = people
       // with thumbnails
       .filter((person) => !!person.thumbnailPath)

+ 10 - 4
server/src/infra/repositories/person.repository.ts

@@ -51,16 +51,22 @@ export class PersonRepository implements IPersonRepository {
   }
 
   getAll(userId: string, options?: PersonSearchOptions): Promise<PersonEntity[]> {
-    return this.personRepository
+    const queryBuilder = this.personRepository
       .createQueryBuilder('person')
       .leftJoin('person.faces', 'face')
       .where('person.ownerId = :userId', { userId })
-      .orderBy('COUNT(face.assetId)', 'DESC')
+      .orderBy('person.isHidden', 'ASC')
+      .addOrderBy("NULLIF(person.name, '') IS NULL", 'ASC')
+      .addOrderBy('COUNT(face.assetId)', 'DESC')
       .addOrderBy("NULLIF(person.name, '')", 'ASC', 'NULLS LAST')
       .having('COUNT(face.assetId) >= :faces', { faces: options?.minimumFaceCount || 1 })
       .groupBy('person.id')
-      .limit(500)
-      .getMany();
+      .limit(500);
+    if (!options?.withHidden) {
+      queryBuilder.andWhere('person.isHidden = false');
+    }
+
+    return queryBuilder.getMany();
   }
 
   getAllWithoutFaces(): Promise<PersonEntity[]> {