mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
better query, add medium test
This commit is contained in:
parent
ce10c27d7a
commit
2879ded8b0
2 changed files with 54 additions and 16 deletions
|
|
@ -592,7 +592,7 @@ export class AssetRepository {
|
||||||
@GenerateSql({
|
@GenerateSql({
|
||||||
params: [DummyValue.TIME_BUCKET, { withStacked: true }],
|
params: [DummyValue.TIME_BUCKET, { withStacked: true }],
|
||||||
})
|
})
|
||||||
getTimeBucket(timeBucket: string, options: TimeBucketOptions, auth?: AuthDto) {
|
getTimeBucket(timeBucket: string, options: TimeBucketOptions, auth: AuthDto) {
|
||||||
const query = this.db
|
const query = this.db
|
||||||
.with('cte', (qb) =>
|
.with('cte', (qb) =>
|
||||||
qb
|
qb
|
||||||
|
|
@ -602,7 +602,7 @@ export class AssetRepository {
|
||||||
'asset.duration',
|
'asset.duration',
|
||||||
'asset.id',
|
'asset.id',
|
||||||
'asset.visibility',
|
'asset.visibility',
|
||||||
'asset.isFavorite',
|
sql`asset."isFavorite" and asset."ownerId" = ${auth.user.id}`.as('isFavorite'),
|
||||||
sql`asset.type = 'IMAGE'`.as('isImage'),
|
sql`asset.type = 'IMAGE'`.as('isImage'),
|
||||||
sql`asset."deletedAt" is not null`.as('isTrashed'),
|
sql`asset."deletedAt" is not null`.as('isTrashed'),
|
||||||
'asset.livePhotoVideoId',
|
'asset.livePhotoVideoId',
|
||||||
|
|
@ -691,19 +691,7 @@ export class AssetRepository {
|
||||||
eb.fn.coalesce(eb.fn('array_agg', ['duration']), sql.lit('{}')).as('duration'),
|
eb.fn.coalesce(eb.fn('array_agg', ['duration']), sql.lit('{}')).as('duration'),
|
||||||
eb.fn.coalesce(eb.fn('array_agg', ['id']), sql.lit('{}')).as('id'),
|
eb.fn.coalesce(eb.fn('array_agg', ['id']), sql.lit('{}')).as('id'),
|
||||||
eb.fn.coalesce(eb.fn('array_agg', ['visibility']), sql.lit('{}')).as('visibility'),
|
eb.fn.coalesce(eb.fn('array_agg', ['visibility']), sql.lit('{}')).as('visibility'),
|
||||||
eb.fn
|
eb.fn.coalesce(eb.fn('array_agg', ['isFavorite']), sql.lit('{}')).as('isFavorite'),
|
||||||
.coalesce(
|
|
||||||
eb.fn('array_agg', [
|
|
||||||
eb
|
|
||||||
.case()
|
|
||||||
.when(eb.ref('ownerId'), '=', auth?.user.id || '')
|
|
||||||
.then(eb.ref('isFavorite'))
|
|
||||||
.else(sql.lit(false))
|
|
||||||
.end(),
|
|
||||||
]),
|
|
||||||
sql.lit('{}'),
|
|
||||||
)
|
|
||||||
.as('isFavorite'),
|
|
||||||
eb.fn.coalesce(eb.fn('array_agg', ['isImage']), sql.lit('{}')).as('isImage'),
|
eb.fn.coalesce(eb.fn('array_agg', ['isImage']), sql.lit('{}')).as('isImage'),
|
||||||
// TODO: isTrashed is redundant as it will always be all true or false depending on the options
|
// TODO: isTrashed is redundant as it will always be all true or false depending on the options
|
||||||
eb.fn.coalesce(eb.fn('array_agg', ['isTrashed']), sql.lit('{}')).as('isTrashed'),
|
eb.fn.coalesce(eb.fn('array_agg', ['isTrashed']), sql.lit('{}')).as('isTrashed'),
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { AssetVisibility } from 'src/enum';
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { PartnerRepository } from 'src/repositories/partner.repository';
|
||||||
import { DB } from 'src/schema';
|
import { DB } from 'src/schema';
|
||||||
import { TimelineService } from 'src/services/timeline.service';
|
import { TimelineService } from 'src/services/timeline.service';
|
||||||
import { newMediumService } from 'test/medium.factory';
|
import { newMediumService } from 'test/medium.factory';
|
||||||
|
|
@ -15,7 +16,7 @@ let defaultDatabase: Kysely<DB>;
|
||||||
const setup = (db?: Kysely<DB>) => {
|
const setup = (db?: Kysely<DB>) => {
|
||||||
return newMediumService(TimelineService, {
|
return newMediumService(TimelineService, {
|
||||||
database: db || defaultDatabase,
|
database: db || defaultDatabase,
|
||||||
real: [AssetRepository, AccessRepository],
|
real: [AssetRepository, AccessRepository, PartnerRepository],
|
||||||
mock: [LoggingRepository],
|
mock: [LoggingRepository],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -155,5 +156,54 @@ describe(TimelineService.name, () => {
|
||||||
const response = JSON.parse(rawResponse);
|
const response = JSON.parse(rawResponse);
|
||||||
expect(response).toEqual(expect.objectContaining({ isTrashed: [true] }));
|
expect(response).toEqual(expect.objectContaining({ isTrashed: [true] }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return false for favorite status unless asset owner', async () => {
|
||||||
|
const { sut, ctx } = setup();
|
||||||
|
const [{ asset: asset1 }, { asset: asset2 }] = await Promise.all([
|
||||||
|
ctx.newUser().then(async ({ user }) => {
|
||||||
|
const result = await ctx.newAsset({
|
||||||
|
ownerId: user.id,
|
||||||
|
fileCreatedAt: new Date('1970-02-12'),
|
||||||
|
localDateTime: new Date('1970-02-12'),
|
||||||
|
isFavorite: true,
|
||||||
|
});
|
||||||
|
await ctx.newExif({ assetId: result.asset.id, make: 'Canon' });
|
||||||
|
return result;
|
||||||
|
}),
|
||||||
|
ctx.newUser().then(async ({ user }) => {
|
||||||
|
const result = await ctx.newAsset({
|
||||||
|
ownerId: user.id,
|
||||||
|
fileCreatedAt: new Date('1970-02-13'),
|
||||||
|
localDateTime: new Date('1970-02-13'),
|
||||||
|
isFavorite: true,
|
||||||
|
});
|
||||||
|
await ctx.newExif({ assetId: result.asset.id, make: 'Canon' });
|
||||||
|
return result;
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
ctx.newPartner({ sharedById: asset1.ownerId, sharedWithId: asset2.ownerId }),
|
||||||
|
ctx.newPartner({ sharedById: asset2.ownerId, sharedWithId: asset1.ownerId }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const auth1 = factory.auth({ user: { id: asset1.ownerId } });
|
||||||
|
const rawResponse1 = await sut.getTimeBucket(auth1, {
|
||||||
|
timeBucket: '1970-02-01',
|
||||||
|
withPartners: true,
|
||||||
|
visibility: AssetVisibility.Timeline,
|
||||||
|
});
|
||||||
|
const response1 = JSON.parse(rawResponse1);
|
||||||
|
expect(response1).toEqual(expect.objectContaining({ id: [asset2.id, asset1.id], isFavorite: [false, true] }));
|
||||||
|
|
||||||
|
const auth2 = factory.auth({ user: { id: asset2.ownerId } });
|
||||||
|
const rawResponse2 = await sut.getTimeBucket(auth2, {
|
||||||
|
timeBucket: '1970-02-01',
|
||||||
|
withPartners: true,
|
||||||
|
visibility: AssetVisibility.Timeline,
|
||||||
|
});
|
||||||
|
const response2 = JSON.parse(rawResponse2);
|
||||||
|
expect(response2).toEqual(expect.objectContaining({ id: [asset2.id, asset1.id], isFavorite: [true, false] }));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue