mirror of
https://github.com/immich-app/immich.git
synced 2024-12-28 22:51:59 +00:00
refactor(server): move filters to getByDayOfYear query (#14628)
move filters to getByDayOfYear query
This commit is contained in:
parent
25ca3b1124
commit
9eff1c4b34
5 changed files with 55 additions and 38 deletions
|
@ -146,6 +146,11 @@ export interface UpsertFileOptions {
|
||||||
|
|
||||||
export type AssetPathEntity = Pick<AssetEntity, 'id' | 'originalPath' | 'isOffline'>;
|
export type AssetPathEntity = Pick<AssetEntity, 'id' | 'originalPath' | 'isOffline'>;
|
||||||
|
|
||||||
|
export interface DayOfYearAssets {
|
||||||
|
yearsAgo: number;
|
||||||
|
assets: AssetEntity[];
|
||||||
|
}
|
||||||
|
|
||||||
export const IAssetRepository = 'IAssetRepository';
|
export const IAssetRepository = 'IAssetRepository';
|
||||||
|
|
||||||
export interface IAssetRepository {
|
export interface IAssetRepository {
|
||||||
|
@ -156,7 +161,7 @@ export interface IAssetRepository {
|
||||||
select?: FindOptionsSelect<AssetEntity>,
|
select?: FindOptionsSelect<AssetEntity>,
|
||||||
): Promise<AssetEntity[]>;
|
): Promise<AssetEntity[]>;
|
||||||
getByIdsWithAllRelations(ids: string[]): Promise<AssetEntity[]>;
|
getByIdsWithAllRelations(ids: string[]): Promise<AssetEntity[]>;
|
||||||
getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise<AssetEntity[]>;
|
getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise<DayOfYearAssets[]>;
|
||||||
getByChecksum(options: { ownerId: string; checksum: Buffer; libraryId?: string }): Promise<AssetEntity | null>;
|
getByChecksum(options: { ownerId: string; checksum: Buffer; libraryId?: string }): Promise<AssetEntity | null>;
|
||||||
getByChecksums(userId: string, checksums: Buffer[]): Promise<AssetEntity[]>;
|
getByChecksums(userId: string, checksums: Buffer[]): Promise<AssetEntity[]>;
|
||||||
getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined>;
|
getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined>;
|
||||||
|
|
|
@ -68,22 +68,19 @@ SELECT
|
||||||
FROM
|
FROM
|
||||||
"assets" "entity"
|
"assets" "entity"
|
||||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "entity"."id"
|
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "entity"."id"
|
||||||
LEFT JOIN "asset_files" "files" ON "files"."assetId" = "entity"."id"
|
INNER JOIN "asset_files" "files" ON "files"."assetId" = "entity"."id"
|
||||||
WHERE
|
WHERE
|
||||||
(
|
(
|
||||||
"entity"."ownerId" IN ($1)
|
"files"."type" = $1
|
||||||
AND "entity"."isVisible" = true
|
|
||||||
AND "entity"."isArchived" = false
|
|
||||||
AND EXTRACT(
|
AND EXTRACT(
|
||||||
DAY
|
YEAR
|
||||||
|
FROM
|
||||||
|
CURRENT_DATE AT TIME ZONE 'UTC'
|
||||||
|
) - EXTRACT(
|
||||||
|
YEAR
|
||||||
FROM
|
FROM
|
||||||
"entity"."localDateTime" AT TIME ZONE 'UTC'
|
"entity"."localDateTime" AT TIME ZONE 'UTC'
|
||||||
) = $2
|
) > 0
|
||||||
AND EXTRACT(
|
|
||||||
MONTH
|
|
||||||
FROM
|
|
||||||
"entity"."localDateTime" AT TIME ZONE 'UTC'
|
|
||||||
) = $3
|
|
||||||
)
|
)
|
||||||
AND ("entity"."deletedAt" IS NULL)
|
AND ("entity"."deletedAt" IS NULL)
|
||||||
ORDER BY
|
ORDER BY
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
AssetUpdateAllOptions,
|
AssetUpdateAllOptions,
|
||||||
AssetUpdateDuplicateOptions,
|
AssetUpdateDuplicateOptions,
|
||||||
AssetUpdateOptions,
|
AssetUpdateOptions,
|
||||||
|
DayOfYearAssets,
|
||||||
IAssetRepository,
|
IAssetRepository,
|
||||||
LivePhotoSearchOptions,
|
LivePhotoSearchOptions,
|
||||||
MonthDay,
|
MonthDay,
|
||||||
|
@ -74,8 +75,8 @@ export class AssetRepository implements IAssetRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [[DummyValue.UUID], { day: 1, month: 1 }] })
|
@GenerateSql({ params: [[DummyValue.UUID], { day: 1, month: 1 }] })
|
||||||
getByDayOfYear(ownerIds: string[], { day, month }: MonthDay): Promise<AssetEntity[]> {
|
async getByDayOfYear(ownerIds: string[], { day, month }: MonthDay): Promise<DayOfYearAssets[]> {
|
||||||
return this.repository
|
const assets = await this.repository
|
||||||
.createQueryBuilder('entity')
|
.createQueryBuilder('entity')
|
||||||
.where(
|
.where(
|
||||||
`entity.ownerId IN (:...ownerIds)
|
`entity.ownerId IN (:...ownerIds)
|
||||||
|
@ -90,9 +91,25 @@ export class AssetRepository implements IAssetRepository {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.leftJoinAndSelect('entity.exifInfo', 'exifInfo')
|
.leftJoinAndSelect('entity.exifInfo', 'exifInfo')
|
||||||
.leftJoinAndSelect('entity.files', 'files')
|
.innerJoinAndSelect('entity.files', 'files')
|
||||||
|
.where('files.type = :type', { type: AssetFileType.THUMBNAIL })
|
||||||
|
.andWhere(
|
||||||
|
`EXTRACT(YEAR FROM CURRENT_DATE AT TIME ZONE 'UTC') - EXTRACT(YEAR FROM entity.localDateTime AT TIME ZONE 'UTC') > 0`,
|
||||||
|
)
|
||||||
.orderBy('entity.fileCreatedAt', 'ASC')
|
.orderBy('entity.fileCreatedAt', 'ASC')
|
||||||
.getMany();
|
.getMany();
|
||||||
|
|
||||||
|
const groups: Record<number, DayOfYearAssets> = {};
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
for (const asset of assets) {
|
||||||
|
const yearsAgo = currentYear - asset.localDateTime.getFullYear();
|
||||||
|
if (!groups[yearsAgo]) {
|
||||||
|
groups[yearsAgo] = { yearsAgo, assets: [] };
|
||||||
|
}
|
||||||
|
groups[yearsAgo].assets.push(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.values(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [[DummyValue.UUID]] })
|
@GenerateSql({ params: [[DummyValue.UUID]] })
|
||||||
|
|
|
@ -80,7 +80,20 @@ describe(AssetService.name, () => {
|
||||||
const image4 = { ...assetStub.image, localDateTime: new Date(2009, 1, 15) };
|
const image4 = { ...assetStub.image, localDateTime: new Date(2009, 1, 15) };
|
||||||
|
|
||||||
partnerMock.getAll.mockResolvedValue([]);
|
partnerMock.getAll.mockResolvedValue([]);
|
||||||
assetMock.getByDayOfYear.mockResolvedValue([image1, image2, image3, image4]);
|
assetMock.getByDayOfYear.mockResolvedValue([
|
||||||
|
{
|
||||||
|
yearsAgo: 1,
|
||||||
|
assets: [image1, image2],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yearsAgo: 9,
|
||||||
|
assets: [image3],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yearsAgo: 15,
|
||||||
|
assets: [image4],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
await expect(sut.getMemoryLane(authStub.admin, { day: 15, month: 1 })).resolves.toEqual([
|
await expect(sut.getMemoryLane(authStub.admin, { day: 15, month: 1 })).resolves.toEqual([
|
||||||
{ yearsAgo: 1, title: '1 year ago', assets: [mapAsset(image1), mapAsset(image2)] },
|
{ yearsAgo: 1, title: '1 year ago', assets: [mapAsset(image1), mapAsset(image2)] },
|
||||||
|
|
|
@ -43,28 +43,13 @@ export class AssetService extends BaseService {
|
||||||
});
|
});
|
||||||
const userIds = [auth.user.id, ...partnerIds];
|
const userIds = [auth.user.id, ...partnerIds];
|
||||||
|
|
||||||
const assets = await this.assetRepository.getByDayOfYear(userIds, dto);
|
const groups = await this.assetRepository.getByDayOfYear(userIds, dto);
|
||||||
const assetsWithThumbnails = assets.filter(({ files }) => !!getAssetFiles(files).thumbnailFile);
|
return groups.map(({ yearsAgo, assets }) => ({
|
||||||
const groups: Record<number, AssetEntity[]> = {};
|
yearsAgo,
|
||||||
const currentYear = new Date().getFullYear();
|
// TODO move this to clients
|
||||||
for (const asset of assetsWithThumbnails) {
|
title: `${yearsAgo} year${yearsAgo > 1 ? 's' : ''} ago`,
|
||||||
const yearsAgo = currentYear - asset.localDateTime.getFullYear();
|
assets: assets.map((asset) => mapAsset(asset, { auth })),
|
||||||
if (!groups[yearsAgo]) {
|
}));
|
||||||
groups[yearsAgo] = [];
|
|
||||||
}
|
|
||||||
groups[yearsAgo].push(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(groups)
|
|
||||||
.map(Number)
|
|
||||||
.sort((a, b) => a - b)
|
|
||||||
.filter((yearsAgo) => yearsAgo > 0)
|
|
||||||
.map((yearsAgo) => ({
|
|
||||||
yearsAgo,
|
|
||||||
// TODO move this to clients
|
|
||||||
title: `${yearsAgo} year${yearsAgo > 1 ? 's' : ''} ago`,
|
|
||||||
assets: groups[yearsAgo].map((asset) => mapAsset(asset, { auth })),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getStatistics(auth: AuthDto, dto: AssetStatsDto) {
|
async getStatistics(auth: AuthDto, dto: AssetStatsDto) {
|
||||||
|
|
Loading…
Reference in a new issue