Skip to content

Commit

Permalink
fix(server): search suggestions include partner assets (immich-app#12269
Browse files Browse the repository at this point in the history
)

search suggestions now include partner assets

Co-authored-by: Alex <[email protected]>
  • Loading branch information
Lukasdotcom and alextran1502 authored Sep 5, 2024
1 parent 259bc8a commit 27e283e
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 25 deletions.
10 changes: 5 additions & 5 deletions server/src/interfaces/metadata.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ export interface IMetadataRepository {
readTags(path: string): Promise<ImmichTags | null>;
writeTags(path: string, tags: Partial<Tags>): Promise<void>;
extractBinaryTag(tagName: string, path: string): Promise<Buffer>;
getCountries(userId: string): Promise<Array<string | null>>;
getStates(userId: string, country?: string): Promise<Array<string | null>>;
getCities(userId: string, country?: string, state?: string): Promise<Array<string | null>>;
getCameraMakes(userId: string, model?: string): Promise<Array<string | null>>;
getCameraModels(userId: string, make?: string): Promise<Array<string | null>>;
getCountries(userIds: string[]): Promise<Array<string | null>>;
getStates(userIds: string[], country?: string): Promise<Array<string | null>>;
getCities(userIds: string[], country?: string, state?: string): Promise<Array<string | null>>;
getCameraMakes(userIds: string[], model?: string): Promise<Array<string | null>>;
getCameraModels(userIds: string[], make?: string): Promise<Array<string | null>>;
}
20 changes: 10 additions & 10 deletions server/src/repositories/metadata.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ export class MetadataRepository implements IMetadataRepository {
}

@GenerateSql({ params: [DummyValue.UUID] })
async getCountries(userId: string): Promise<string[]> {
async getCountries(userIds: string[]): Promise<string[]> {
const results = await this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.where('asset.ownerId IN (:...userIds )', { userIds })
.select('exif.country', 'country')
.distinctOn(['exif.country'])
.getRawMany<{ country: string }>();
Expand All @@ -69,11 +69,11 @@ export class MetadataRepository implements IMetadataRepository {
}

@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
async getStates(userId: string, country: string | undefined): Promise<string[]> {
async getStates(userIds: string[], country: string | undefined): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.where('asset.ownerId IN (:...userIds )', { userIds })
.select('exif.state', 'state')
.distinctOn(['exif.state']);

Expand All @@ -87,11 +87,11 @@ export class MetadataRepository implements IMetadataRepository {
}

@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING, DummyValue.STRING] })
async getCities(userId: string, country: string | undefined, state: string | undefined): Promise<string[]> {
async getCities(userIds: string[], country: string | undefined, state: string | undefined): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.where('asset.ownerId IN (:...userIds )', { userIds })
.select('exif.city', 'city')
.distinctOn(['exif.city']);

Expand All @@ -109,11 +109,11 @@ export class MetadataRepository implements IMetadataRepository {
}

@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
async getCameraMakes(userId: string, model: string | undefined): Promise<string[]> {
async getCameraMakes(userIds: string[], model: string | undefined): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.where('asset.ownerId IN (:...userIds )', { userIds })
.select('exif.make', 'make')
.distinctOn(['exif.make']);

Expand All @@ -126,11 +126,11 @@ export class MetadataRepository implements IMetadataRepository {
}

@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
async getCameraModels(userId: string, make: string | undefined): Promise<string[]> {
async getCameraModels(userIds: string[], make: string | undefined): Promise<string[]> {
const query = this.exifRepository
.createQueryBuilder('exif')
.leftJoin('exif.asset', 'asset')
.where('asset.ownerId = :userId', { userId })
.where('asset.ownerId IN (:...userIds )', { userIds })
.select('exif.model', 'model')
.distinctOn(['exif.model']);

Expand Down
4 changes: 2 additions & 2 deletions server/src/services/search.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ describe(SearchService.name, () => {
await expect(
sut.getSearchSuggestions(authStub.user1, { includeNull: true, type: SearchSuggestionType.COUNTRY }),
).resolves.toEqual(['USA', null]);
expect(metadataMock.getCountries).toHaveBeenCalledWith(authStub.user1.user.id);
expect(metadataMock.getCountries).toHaveBeenCalledWith([authStub.user1.user.id]);
});

it('should return search suggestions (without null)', async () => {
metadataMock.getCountries.mockResolvedValue(['USA', null]);
await expect(
sut.getSearchSuggestions(authStub.user1, { includeNull: false, type: SearchSuggestionType.COUNTRY }),
).resolves.toEqual(['USA']);
expect(metadataMock.getCountries).toHaveBeenCalledWith(authStub.user1.user.id);
expect(metadataMock.getCountries).toHaveBeenCalledWith([authStub.user1.user.id]);
});
});
});
15 changes: 8 additions & 7 deletions server/src/services/search.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,26 +121,27 @@ export class SearchService {
}

async getSearchSuggestions(auth: AuthDto, dto: SearchSuggestionRequestDto) {
const results = await this.getSuggestions(auth.user.id, dto);
const userIds = await this.getUserIdsToSearch(auth);
const results = await this.getSuggestions(userIds, dto);
return results.filter((result) => (dto.includeNull ? true : result !== null));
}

private getSuggestions(userId: string, dto: SearchSuggestionRequestDto) {
private getSuggestions(userIds: string[], dto: SearchSuggestionRequestDto) {
switch (dto.type) {
case SearchSuggestionType.COUNTRY: {
return this.metadataRepository.getCountries(userId);
return this.metadataRepository.getCountries(userIds);
}
case SearchSuggestionType.STATE: {
return this.metadataRepository.getStates(userId, dto.country);
return this.metadataRepository.getStates(userIds, dto.country);
}
case SearchSuggestionType.CITY: {
return this.metadataRepository.getCities(userId, dto.country, dto.state);
return this.metadataRepository.getCities(userIds, dto.country, dto.state);
}
case SearchSuggestionType.CAMERA_MAKE: {
return this.metadataRepository.getCameraMakes(userId, dto.model);
return this.metadataRepository.getCameraMakes(userIds, dto.model);
}
case SearchSuggestionType.CAMERA_MODEL: {
return this.metadataRepository.getCameraModels(userId, dto.make);
return this.metadataRepository.getCameraModels(userIds, dto.make);
}
default: {
return [];
Expand Down
2 changes: 1 addition & 1 deletion server/test/repositories/partner.repository.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const newPartnerRepositoryMock = (): Mocked<IPartnerRepository> => {
return {
create: vitest.fn(),
remove: vitest.fn(),
getAll: vitest.fn(),
getAll: vitest.fn().mockResolvedValue([]),
get: vitest.fn(),
update: vitest.fn(),
};
Expand Down

0 comments on commit 27e283e

Please sign in to comment.