refactor(server): use includeNull in query for search suggestions (#14626)

* use `includeNull`

* push down `includeNull` into query, inner joins

* remove filter

* update sql

* fix tests

* maybe fix e2e

* more e2e tests

* handle no exif row

* whoops

* update sql
This commit is contained in:
Mert
2024-12-10 16:22:37 -05:00
committed by GitHub
parent 60c783bbe9
commit 25ca3b1124
6 changed files with 259 additions and 52 deletions

View File

@@ -17,6 +17,10 @@ import {
AssetSearchOptions,
FaceEmbeddingSearch,
FaceSearchResult,
GetCameraMakesOptions,
GetCameraModelsOptions,
GetCitiesOptions,
GetStatesOptions,
ISearchRepository,
SearchPaginationOptions,
SmartSearchOptions,
@@ -342,23 +346,27 @@ export class SearchRepository implements ISearchRepository {
@GenerateSql({ params: [[DummyValue.UUID]] })
async getCountries(userIds: string[]): Promise<string[]> {
const results = await this.exifRepository
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.innerJoin('exif.asset', 'asset')
.where('asset.ownerId IN (:...userIds )', { userIds })
.andWhere(`exif.country != ''`)
.andWhere('exif.country IS NOT NULL')
.select('exif.country', 'country')
.distinctOn(['exif.country'])
.getRawMany<{ country: string }>();
.distinctOn(['exif.country']);
return results.map(({ country }) => country).filter((item) => item !== '');
const results = await query.getRawMany<{ country: string }>();
return results.map(({ country }) => country);
}
@GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] })
async getStates(userIds: string[], country: string | undefined): Promise<string[]> {
async getStates(userIds: string[], { country }: GetStatesOptions): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.innerJoin('exif.asset', 'asset')
.where('asset.ownerId IN (:...userIds )', { userIds })
.andWhere(`exif.state != ''`)
.andWhere('exif.state IS NOT NULL')
.select('exif.state', 'state')
.distinctOn(['exif.state']);
@@ -367,16 +375,17 @@ export class SearchRepository implements ISearchRepository {
}
const result = await query.getRawMany<{ state: string }>();
return result.map(({ state }) => state).filter((item) => item !== '');
return result.map(({ state }) => state);
}
@GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING, DummyValue.STRING] })
async getCities(userIds: string[], country: string | undefined, state: string | undefined): Promise<string[]> {
async getCities(userIds: string[], { country, state }: GetCitiesOptions): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.innerJoin('exif.asset', 'asset')
.where('asset.ownerId IN (:...userIds )', { userIds })
.andWhere(`exif.city != ''`)
.andWhere('exif.city IS NOT NULL')
.select('exif.city', 'city')
.distinctOn(['exif.city']);
@@ -389,16 +398,17 @@ export class SearchRepository implements ISearchRepository {
}
const results = await query.getRawMany<{ city: string }>();
return results.map(({ city }) => city).filter((item) => item !== '');
return results.map(({ city }) => city);
}
@GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] })
async getCameraMakes(userIds: string[], model: string | undefined): Promise<string[]> {
async getCameraMakes(userIds: string[], { model }: GetCameraMakesOptions): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.innerJoin('exif.asset', 'asset')
.where('asset.ownerId IN (:...userIds )', { userIds })
.andWhere(`exif.make != ''`)
.andWhere('exif.make IS NOT NULL')
.select('exif.make', 'make')
.distinctOn(['exif.make']);
@@ -407,15 +417,17 @@ export class SearchRepository implements ISearchRepository {
}
const results = await query.getRawMany<{ make: string }>();
return results.map(({ make }) => make).filter((item) => item !== '');
return results.map(({ make }) => make);
}
@GenerateSql({ params: [[DummyValue.UUID], DummyValue.STRING] })
async getCameraModels(userIds: string[], make: string | undefined): Promise<string[]> {
async getCameraModels(userIds: string[], { make }: GetCameraModelsOptions): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.innerJoin('exif.asset', 'asset')
.where('asset.ownerId IN (:...userIds )', { userIds })
.andWhere(`exif.model != ''`)
.andWhere('exif.model IS NOT NULL')
.select('exif.model', 'model')
.distinctOn(['exif.model']);
@@ -424,7 +436,7 @@ export class SearchRepository implements ISearchRepository {
}
const results = await query.getRawMany<{ model: string }>();
return results.map(({ model }) => model).filter((item) => item !== '');
return results.map(({ model }) => model);
}
private getRuntimeConfig(numResults?: number): string | undefined {