diff --git a/server/src/queries/person.repository.sql b/server/src/queries/person.repository.sql index a2f3f64442..991eb13adc 100644 --- a/server/src/queries/person.repository.sql +++ b/server/src/queries/person.repository.sql @@ -28,38 +28,44 @@ select "person".* from "person" - inner join "asset_face" on "asset_face"."personId" = "person"."id" - inner join "asset" on "asset_face"."assetId" = "asset"."id" - and "asset"."visibility" = 'timeline' - and "asset"."deletedAt" is null + inner join ( + select + "asset_face"."personId" as "personId", + count("asset_face"."assetId") as "faceCount" + from + "asset_face" + inner join "asset" on "asset_face"."assetId" = "asset"."id" + and "asset"."visibility" = 'timeline' + and "asset"."deletedAt" is null + where + "asset_face"."deletedAt" is null + and "asset_face"."isVisible" is true + group by + "asset_face"."personId" + ) as "face_counts" on "face_counts"."personId" = "person"."id" where "person"."ownerId" = $1 - and "asset_face"."deletedAt" is null - and "asset_face"."isVisible" is true - and "person"."isHidden" = $2 -group by - "person"."id" -having - ( - "person"."name" != $3 - or count("asset_face"."assetId") >= COALESCE( + and ( + "person"."name" != $2 + or "face_counts"."faceCount" >= COALESCE( ( SELECT value -> 'people' ->> 'minimumFaces' FROM user_metadata WHERE - "userId" = $4 + "userId" = $3 AND key = 'preferences' ), '3' )::int ) + and "person"."isHidden" = $4 order by "person"."isHidden" asc, "person"."isFavorite" desc, NULLIF(person.name, '') is null asc, - count("asset_face"."assetId") desc, + "face_counts"."faceCount" desc, NULLIF(person.name, '') asc nulls last, "person"."createdAt" limit diff --git a/server/src/repositories/person.repository.ts b/server/src/repositories/person.repository.ts index 0db03a18c7..489b68775f 100644 --- a/server/src/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -149,26 +149,29 @@ export class PersonRepository { @GenerateSql({ params: [{ take: 1, skip: 0 }, DummyValue.UUID] }) async getAllForUser(pagination: PaginationOptions, userId: string, options?: PersonSearchOptions) { - const items = await this.db - .selectFrom('person') - .selectAll('person') - .innerJoin('asset_face', 'asset_face.personId', 'person.id') + const faceCounts = this.db + .selectFrom('asset_face') .innerJoin('asset', (join) => join .onRef('asset_face.assetId', '=', 'asset.id') .on('asset.visibility', '=', sql.lit(AssetVisibility.Timeline)) .on('asset.deletedAt', 'is', null), ) - .where('person.ownerId', '=', userId) + .select(['asset_face.personId as personId', (eb) => eb.fn.count('asset_face.assetId').as('faceCount')]) .where('asset_face.deletedAt', 'is', null) .where('asset_face.isVisible', 'is', true) - .orderBy('person.isHidden', 'asc') - .orderBy('person.isFavorite', 'desc') - .having((eb) => + .groupBy('asset_face.personId'); + + const items = await this.db + .selectFrom('person') + .selectAll('person') + .innerJoin(faceCounts.as('face_counts'), 'face_counts.personId', 'person.id') + .where('person.ownerId', '=', userId) + .where((eb) => eb.or([ eb('person.name', '!=', ''), eb( - (innerEb) => innerEb.fn.count('asset_face.assetId'), + 'face_counts.faceCount', '>=', sql`COALESCE( (SELECT value -> 'people' ->> 'minimumFaces' @@ -180,7 +183,8 @@ export class PersonRepository { ), ]), ) - .groupBy('person.id') + .orderBy('person.isHidden', 'asc') + .orderBy('person.isFavorite', 'desc') .$if(!!options?.closestFaceAssetId, (qb) => qb.orderBy((eb) => eb( @@ -201,7 +205,7 @@ export class PersonRepository { .$if(!options?.closestFaceAssetId, (qb) => qb .orderBy(sql`NULLIF(person.name, '') is null`, 'asc') - .orderBy((eb) => eb.fn.count('asset_face.assetId'), 'desc') + .orderBy('face_counts.faceCount', 'desc') .orderBy(sql`NULLIF(person.name, '')`, (om) => om.asc().nullsLast()) .orderBy('person.createdAt'), )