mirror of
https://github.com/immich-app/immich.git
synced 2026-03-04 09:57:33 +03:00
refactor: asset v1, app.utils (#8152)
This commit is contained in:
153
server/src/repositories/asset-v1.repository.ts
Normal file
153
server/src/repositories/asset-v1.repository.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { CuratedLocationsResponseDto, CuratedObjectsResponseDto } from 'src/dtos/asset-v1-response.dto';
|
||||
import { AssetSearchDto, CheckExistingAssetsDto, SearchPropertiesDto } from 'src/dtos/asset-v1.dto';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { AssetCheck, AssetOwnerCheck, IAssetRepositoryV1 } from 'src/interfaces/asset-v1.interface';
|
||||
import { OptionalBetween } from 'src/utils/database';
|
||||
import { In } from 'typeorm/find-options/operator/In.js';
|
||||
import { Repository } from 'typeorm/repository/Repository.js';
|
||||
|
||||
@Injectable()
|
||||
export class AssetRepositoryV1 implements IAssetRepositoryV1 {
|
||||
constructor(@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>) {}
|
||||
|
||||
/**
|
||||
* Retrieves all assets by user ID.
|
||||
*
|
||||
* @param ownerId - The ID of the owner.
|
||||
* @param dto - The AssetSearchDto object containing search criteria.
|
||||
* @returns A Promise that resolves to an array of AssetEntity objects.
|
||||
*/
|
||||
getAllByUserId(ownerId: string, dto: AssetSearchDto): Promise<AssetEntity[]> {
|
||||
return this.assetRepository.find({
|
||||
where: {
|
||||
ownerId,
|
||||
isVisible: true,
|
||||
isFavorite: dto.isFavorite,
|
||||
isArchived: dto.isArchived,
|
||||
updatedAt: OptionalBetween(dto.updatedAfter, dto.updatedBefore),
|
||||
},
|
||||
relations: {
|
||||
exifInfo: true,
|
||||
tags: true,
|
||||
stack: { assets: true },
|
||||
},
|
||||
skip: dto.skip || 0,
|
||||
take: dto.take,
|
||||
order: {
|
||||
fileCreatedAt: 'DESC',
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
}
|
||||
|
||||
getSearchPropertiesByUserId(userId: string): Promise<SearchPropertiesDto[]> {
|
||||
return this.assetRepository
|
||||
.createQueryBuilder('asset')
|
||||
.where('asset.ownerId = :userId', { userId: userId })
|
||||
.andWhere('asset.isVisible = true')
|
||||
.leftJoin('asset.exifInfo', 'ei')
|
||||
.leftJoin('asset.smartInfo', 'si')
|
||||
.select('si.tags', 'tags')
|
||||
.addSelect('si.objects', 'objects')
|
||||
.addSelect('asset.type', 'assetType')
|
||||
.addSelect('ei.orientation', 'orientation')
|
||||
.addSelect('ei."lensModel"', 'lensModel')
|
||||
.addSelect('ei.make', 'make')
|
||||
.addSelect('ei.model', 'model')
|
||||
.addSelect('ei.city', 'city')
|
||||
.addSelect('ei.state', 'state')
|
||||
.addSelect('ei.country', 'country')
|
||||
.distinctOn(['si.tags'])
|
||||
.getRawMany();
|
||||
}
|
||||
|
||||
getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]> {
|
||||
return this.assetRepository.query(
|
||||
`
|
||||
SELECT DISTINCT ON (unnest(si.objects)) a.id, unnest(si.objects) as "object", a."resizePath", a."deviceAssetId", a."deviceId"
|
||||
FROM assets a
|
||||
LEFT JOIN smart_info si ON a.id = si."assetId"
|
||||
WHERE a."ownerId" = $1
|
||||
AND a."isVisible" = true
|
||||
AND si.objects IS NOT NULL
|
||||
`,
|
||||
[userId],
|
||||
);
|
||||
}
|
||||
|
||||
getLocationsByUserId(userId: string): Promise<CuratedLocationsResponseDto[]> {
|
||||
return this.assetRepository.query(
|
||||
`
|
||||
SELECT DISTINCT ON (e.city) a.id, e.city, a."resizePath", a."deviceAssetId", a."deviceId"
|
||||
FROM assets a
|
||||
LEFT JOIN exif e ON a.id = e."assetId"
|
||||
WHERE a."ownerId" = $1
|
||||
AND a."isVisible" = true
|
||||
AND e.city IS NOT NULL
|
||||
AND a.type = 'IMAGE';
|
||||
`,
|
||||
[userId],
|
||||
);
|
||||
}
|
||||
|
||||
get(id: string): Promise<AssetEntity | null> {
|
||||
return this.assetRepository.findOne({
|
||||
where: { id },
|
||||
relations: {
|
||||
faces: {
|
||||
person: true,
|
||||
},
|
||||
library: true,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assets by checksums on the database
|
||||
* @param ownerId
|
||||
* @param checksums
|
||||
*
|
||||
*/
|
||||
getAssetsByChecksums(ownerId: string, checksums: Buffer[]): Promise<AssetCheck[]> {
|
||||
return this.assetRepository.find({
|
||||
select: {
|
||||
id: true,
|
||||
checksum: true,
|
||||
},
|
||||
where: {
|
||||
ownerId,
|
||||
checksum: In(checksums),
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
}
|
||||
|
||||
async getExistingAssets(ownerId: string, checkDuplicateAssetDto: CheckExistingAssetsDto): Promise<string[]> {
|
||||
const assets = await this.assetRepository.find({
|
||||
select: { deviceAssetId: true },
|
||||
where: {
|
||||
deviceAssetId: In(checkDuplicateAssetDto.deviceAssetIds),
|
||||
deviceId: checkDuplicateAssetDto.deviceId,
|
||||
ownerId,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
return assets.map((asset) => asset.deviceAssetId);
|
||||
}
|
||||
|
||||
getByOriginalPath(originalPath: string): Promise<AssetOwnerCheck | null> {
|
||||
return this.assetRepository.findOne({
|
||||
select: {
|
||||
id: true,
|
||||
ownerId: true,
|
||||
checksum: true,
|
||||
},
|
||||
where: {
|
||||
originalPath,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user