mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
refactor(server): bulk interface (#10889)
This commit is contained in:
parent
ac8d8d91f7
commit
cf88f4b6f8
5 changed files with 21 additions and 36 deletions
|
@ -28,10 +28,8 @@ export interface IAlbumRepository extends IBulkAsset {
|
||||||
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null>;
|
getById(id: string, options: AlbumInfoOptions): Promise<AlbumEntity | null>;
|
||||||
getByIds(ids: string[]): Promise<AlbumEntity[]>;
|
getByIds(ids: string[]): Promise<AlbumEntity[]>;
|
||||||
getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]>;
|
getByAssetId(ownerId: string, assetId: string): Promise<AlbumEntity[]>;
|
||||||
getAssetIds(albumId: string, assetIds?: string[]): Promise<Set<string>>;
|
|
||||||
hasAsset(asset: AlbumAsset): Promise<boolean>;
|
hasAsset(asset: AlbumAsset): Promise<boolean>;
|
||||||
removeAsset(assetId: string): Promise<void>;
|
removeAsset(assetId: string): Promise<void>;
|
||||||
removeAssetIds(albumId: string, assetIds: string[]): Promise<void>;
|
|
||||||
getMetadataForIds(ids: string[]): Promise<AlbumAssetCount[]>;
|
getMetadataForIds(ids: string[]): Promise<AlbumAssetCount[]>;
|
||||||
getInvalidThumbnail(): Promise<string[]>;
|
getInvalidThumbnail(): Promise<string[]>;
|
||||||
getOwned(ownerId: string): Promise<AlbumEntity[]>;
|
getOwned(ownerId: string): Promise<AlbumEntity[]>;
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import { MemoryEntity } from 'src/entities/memory.entity';
|
import { MemoryEntity } from 'src/entities/memory.entity';
|
||||||
|
import { IBulkAsset } from 'src/utils/asset.util';
|
||||||
|
|
||||||
export const IMemoryRepository = 'IMemoryRepository';
|
export const IMemoryRepository = 'IMemoryRepository';
|
||||||
|
|
||||||
export interface IMemoryRepository {
|
export interface IMemoryRepository extends IBulkAsset {
|
||||||
search(ownerId: string): Promise<MemoryEntity[]>;
|
search(ownerId: string): Promise<MemoryEntity[]>;
|
||||||
get(id: string): Promise<MemoryEntity | null>;
|
get(id: string): Promise<MemoryEntity | null>;
|
||||||
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
create(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
||||||
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
update(memory: Partial<MemoryEntity>): Promise<MemoryEntity>;
|
||||||
delete(id: string): Promise<void>;
|
delete(id: string): Promise<void>;
|
||||||
getAssetIds(id: string, assetIds: string[]): Promise<Set<string>>;
|
|
||||||
addAssetIds(id: string, assetIds: string[]): Promise<void>;
|
|
||||||
removeAssetIds(id: string, assetIds: string[]): Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,14 +585,6 @@ WHERE
|
||||||
"albums_assets"."albumsId" = $1
|
"albums_assets"."albumsId" = $1
|
||||||
AND "albums_assets"."assetsId" IN ($2)
|
AND "albums_assets"."assetsId" IN ($2)
|
||||||
|
|
||||||
-- AlbumRepository.getAssetIds (no assets)
|
|
||||||
SELECT
|
|
||||||
"albums_assets"."assetsId" AS "assetId"
|
|
||||||
FROM
|
|
||||||
"albums_assets_assets" "albums_assets"
|
|
||||||
WHERE
|
|
||||||
"albums_assets"."albumsId" = $1
|
|
||||||
|
|
||||||
-- AlbumRepository.hasAsset
|
-- AlbumRepository.hasAsset
|
||||||
SELECT
|
SELECT
|
||||||
1 AS "row_exists"
|
1 AS "row_exists"
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||||
import _ from 'lodash';
|
import { Chunked, ChunkedArray, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators';
|
|
||||||
import { AlbumEntity } from 'src/entities/album.entity';
|
import { AlbumEntity } from 'src/entities/album.entity';
|
||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { AlbumAsset, AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
import { AlbumAsset, AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { Instrumentation } from 'src/utils/instrumentation';
|
import { Instrumentation } from 'src/utils/instrumentation';
|
||||||
import { setUnion } from 'src/utils/set';
|
|
||||||
import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
|
import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
|
||||||
|
|
||||||
const withoutDeletedUsers = <T extends AlbumEntity | null>(album: T) => {
|
const withoutDeletedUsers = <T extends AlbumEntity | null>(album: T) => {
|
||||||
|
@ -215,6 +213,10 @@ export class AlbumRepository implements IAlbumRepository {
|
||||||
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
||||||
@Chunked({ paramIndex: 1 })
|
@Chunked({ paramIndex: 1 })
|
||||||
async removeAssetIds(albumId: string, assetIds: string[]): Promise<void> {
|
async removeAssetIds(albumId: string, assetIds: string[]): Promise<void> {
|
||||||
|
if (assetIds.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.dataSource
|
await this.dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.delete()
|
.delete()
|
||||||
|
@ -233,27 +235,22 @@ export class AlbumRepository implements IAlbumRepository {
|
||||||
* @param assetIds Optional list of asset IDs to filter on.
|
* @param assetIds Optional list of asset IDs to filter on.
|
||||||
* @returns Set of Asset IDs for the given album ID.
|
* @returns Set of Asset IDs for the given album ID.
|
||||||
*/
|
*/
|
||||||
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] }, { name: 'no assets', params: [DummyValue.UUID] })
|
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
||||||
async getAssetIds(albumId: string, assetIds?: string[]): Promise<Set<string>> {
|
@ChunkedSet({ paramIndex: 1 })
|
||||||
const query = this.dataSource
|
async getAssetIds(albumId: string, assetIds: string[]): Promise<Set<string>> {
|
||||||
|
if (assetIds.length === 0) {
|
||||||
|
return new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await this.dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select('albums_assets.assetsId', 'assetId')
|
.select('albums_assets.assetsId', 'assetId')
|
||||||
.from('albums_assets_assets', 'albums_assets')
|
.from('albums_assets_assets', 'albums_assets')
|
||||||
.where('"albums_assets"."albumsId" = :albumId', { albumId });
|
.where('"albums_assets"."albumsId" = :albumId', { albumId })
|
||||||
|
.andWhere('"albums_assets"."assetsId" IN (:...assetIds)', { assetIds })
|
||||||
|
.getRawMany<{ assetId: string }>();
|
||||||
|
|
||||||
if (!assetIds?.length) {
|
return new Set(results.map(({ assetId }) => assetId));
|
||||||
const result = await query.getRawMany();
|
|
||||||
return new Set(result.map((row) => row['assetId']));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(
|
|
||||||
_.chunk(assetIds, DATABASE_PARAMETER_CHUNK_SIZE).map((idChunk) =>
|
|
||||||
query
|
|
||||||
.andWhere('"albums_assets"."assetsId" IN (:...assetIds)', { assetIds: idChunk })
|
|
||||||
.getRawMany()
|
|
||||||
.then((result) => new Set(result.map((row) => row['assetId']))),
|
|
||||||
),
|
|
||||||
).then((results) => setUnion(...results));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ albumId: DummyValue.UUID, assetId: DummyValue.UUID }] })
|
||||||
|
|
|
@ -61,9 +61,9 @@ export class MemoryRepository implements IMemoryRepository {
|
||||||
.from('memories_assets_assets', 'memories_assets')
|
.from('memories_assets_assets', 'memories_assets')
|
||||||
.where('"memories_assets"."memoriesId" = :memoryId', { memoryId: id })
|
.where('"memories_assets"."memoriesId" = :memoryId', { memoryId: id })
|
||||||
.andWhere('memories_assets.assetsId IN (:...assetIds)', { assetIds })
|
.andWhere('memories_assets.assetsId IN (:...assetIds)', { assetIds })
|
||||||
.getRawMany();
|
.getRawMany<{ assetId: string }>();
|
||||||
|
|
||||||
return new Set(results.map((row) => row['assetId']));
|
return new Set(results.map(({ assetId }) => assetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
@GenerateSql({ params: [DummyValue.UUID, [DummyValue.UUID]] })
|
||||||
|
|
Loading…
Reference in a new issue