mirror of https://github.com/immich-app/immich.git
refactor(server): use kysely (#12857)
parent
1489d69f81
commit
2e12c46980
@ -0,0 +1,439 @@
|
||||
/**
|
||||
* This file was generated by kysely-codegen.
|
||||
* Please do not edit it manually.
|
||||
*/
|
||||
|
||||
import type { ColumnType } from 'kysely';
|
||||
|
||||
export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>;
|
||||
|
||||
export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[];
|
||||
|
||||
export type AssetsStatusEnum = 'active' | 'deleted' | 'trashed';
|
||||
|
||||
export type Generated<T> =
|
||||
T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>;
|
||||
|
||||
export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>;
|
||||
|
||||
export type Json = JsonValue;
|
||||
|
||||
export type JsonArray = JsonValue[];
|
||||
|
||||
export type JsonObject = {
|
||||
[x: string]: JsonValue | undefined;
|
||||
};
|
||||
|
||||
export type JsonPrimitive = boolean | number | string | null;
|
||||
|
||||
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
|
||||
|
||||
export type Sourcetype = 'exif' | 'machine-learning';
|
||||
|
||||
export type Timestamp = ColumnType<Date, Date | string, Date | string>;
|
||||
|
||||
export interface Activity {
|
||||
albumId: string;
|
||||
assetId: string | null;
|
||||
comment: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
isLiked: Generated<boolean>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface Albums {
|
||||
albumName: Generated<string>;
|
||||
/**
|
||||
* Asset ID to be used as thumbnail
|
||||
*/
|
||||
albumThumbnailAssetId: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
description: Generated<string>;
|
||||
id: Generated<string>;
|
||||
isActivityEnabled: Generated<boolean>;
|
||||
order: Generated<string>;
|
||||
ownerId: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface AlbumsAssetsAssets {
|
||||
albumsId: string;
|
||||
assetsId: string;
|
||||
}
|
||||
|
||||
export interface AlbumsSharedUsersUsers {
|
||||
albumsId: string;
|
||||
role: Generated<string>;
|
||||
usersId: string;
|
||||
}
|
||||
|
||||
export interface ApiKeys {
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
key: string;
|
||||
name: string;
|
||||
permissions: string[];
|
||||
updatedAt: Generated<Timestamp>;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface AssetFaces {
|
||||
assetId: string;
|
||||
boundingBoxX1: Generated<number>;
|
||||
boundingBoxX2: Generated<number>;
|
||||
boundingBoxY1: Generated<number>;
|
||||
boundingBoxY2: Generated<number>;
|
||||
id: Generated<string>;
|
||||
imageHeight: Generated<number>;
|
||||
imageWidth: Generated<number>;
|
||||
personId: string | null;
|
||||
sourceType: Generated<Sourcetype>;
|
||||
}
|
||||
|
||||
export interface AssetFiles {
|
||||
assetId: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
path: string;
|
||||
type: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface AssetJobStatus {
|
||||
assetId: string;
|
||||
duplicatesDetectedAt: Timestamp | null;
|
||||
facesRecognizedAt: Timestamp | null;
|
||||
metadataExtractedAt: Timestamp | null;
|
||||
previewAt: Timestamp | null;
|
||||
thumbnailAt: Timestamp | null;
|
||||
}
|
||||
|
||||
export interface Assets {
|
||||
checksum: Buffer;
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
deviceAssetId: string;
|
||||
deviceId: string;
|
||||
duplicateId: string | null;
|
||||
duration: string | null;
|
||||
encodedVideoPath: Generated<string | null>;
|
||||
fileCreatedAt: Timestamp;
|
||||
fileModifiedAt: Timestamp;
|
||||
id: Generated<string>;
|
||||
isArchived: Generated<boolean>;
|
||||
isExternal: Generated<boolean>;
|
||||
isFavorite: Generated<boolean>;
|
||||
isOffline: Generated<boolean>;
|
||||
isVisible: Generated<boolean>;
|
||||
libraryId: string | null;
|
||||
livePhotoVideoId: string | null;
|
||||
localDateTime: Timestamp;
|
||||
originalFileName: string;
|
||||
originalPath: string;
|
||||
ownerId: string;
|
||||
sidecarPath: string | null;
|
||||
stackId: string | null;
|
||||
status: Generated<AssetsStatusEnum>;
|
||||
thumbhash: Buffer | null;
|
||||
type: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface AssetStack {
|
||||
id: Generated<string>;
|
||||
ownerId: string;
|
||||
primaryAssetId: string;
|
||||
}
|
||||
|
||||
export interface Audit {
|
||||
action: string;
|
||||
createdAt: Generated<Timestamp>;
|
||||
entityId: string;
|
||||
entityType: string;
|
||||
id: Generated<number>;
|
||||
ownerId: string;
|
||||
}
|
||||
|
||||
export interface Exif {
|
||||
assetId: string;
|
||||
autoStackId: string | null;
|
||||
bitsPerSample: number | null;
|
||||
city: string | null;
|
||||
colorspace: string | null;
|
||||
country: string | null;
|
||||
dateTimeOriginal: Timestamp | null;
|
||||
description: Generated<string>;
|
||||
exifImageHeight: number | null;
|
||||
exifImageWidth: number | null;
|
||||
exposureTime: string | null;
|
||||
fileSizeInByte: Int8 | null;
|
||||
fNumber: number | null;
|
||||
focalLength: number | null;
|
||||
fps: number | null;
|
||||
iso: number | null;
|
||||
latitude: number | null;
|
||||
lensModel: string | null;
|
||||
livePhotoCID: string | null;
|
||||
longitude: number | null;
|
||||
make: string | null;
|
||||
model: string | null;
|
||||
modifyDate: Timestamp | null;
|
||||
orientation: string | null;
|
||||
profileDescription: string | null;
|
||||
projectionType: string | null;
|
||||
rating: number | null;
|
||||
state: string | null;
|
||||
timeZone: string | null;
|
||||
}
|
||||
|
||||
export interface FaceSearch {
|
||||
embedding: string;
|
||||
faceId: string;
|
||||
}
|
||||
|
||||
export interface GeodataPlaces {
|
||||
admin1Code: string | null;
|
||||
admin1Name: string | null;
|
||||
admin2Code: string | null;
|
||||
admin2Name: string | null;
|
||||
alternateNames: string | null;
|
||||
countryCode: string;
|
||||
earthCoord: Generated<string | null>;
|
||||
id: number;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
modificationDate: Timestamp;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Libraries {
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
exclusionPatterns: string[];
|
||||
id: Generated<string>;
|
||||
importPaths: string[];
|
||||
name: string;
|
||||
ownerId: string;
|
||||
refreshedAt: Timestamp | null;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface Memories {
|
||||
createdAt: Generated<Timestamp>;
|
||||
data: Json;
|
||||
deletedAt: Timestamp | null;
|
||||
id: Generated<string>;
|
||||
isSaved: Generated<boolean>;
|
||||
memoryAt: Timestamp;
|
||||
ownerId: string;
|
||||
seenAt: Timestamp | null;
|
||||
type: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface MemoriesAssetsAssets {
|
||||
assetsId: string;
|
||||
memoriesId: string;
|
||||
}
|
||||
|
||||
export interface Migrations {
|
||||
id: Generated<number>;
|
||||
name: string;
|
||||
timestamp: Int8;
|
||||
}
|
||||
|
||||
export interface MoveHistory {
|
||||
entityId: string;
|
||||
id: Generated<string>;
|
||||
newPath: string;
|
||||
oldPath: string;
|
||||
pathType: string;
|
||||
}
|
||||
|
||||
export interface NaturalearthCountries {
|
||||
admin: string;
|
||||
admin_a3: string;
|
||||
coordinates: string;
|
||||
id: Generated<number>;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface Partners {
|
||||
createdAt: Generated<Timestamp>;
|
||||
inTimeline: Generated<boolean>;
|
||||
sharedById: string;
|
||||
sharedWithId: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface Person {
|
||||
birthDate: Timestamp | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
faceAssetId: string | null;
|
||||
id: Generated<string>;
|
||||
isHidden: Generated<boolean>;
|
||||
name: Generated<string>;
|
||||
ownerId: string;
|
||||
thumbnailPath: Generated<string>;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface Sessions {
|
||||
createdAt: Generated<Timestamp>;
|
||||
deviceOS: Generated<string>;
|
||||
deviceType: Generated<string>;
|
||||
id: Generated<string>;
|
||||
token: string;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface SharedLinkAsset {
|
||||
assetsId: string;
|
||||
sharedLinksId: string;
|
||||
}
|
||||
|
||||
export interface SharedLinks {
|
||||
albumId: string | null;
|
||||
allowDownload: Generated<boolean>;
|
||||
allowUpload: Generated<boolean>;
|
||||
createdAt: Generated<Timestamp>;
|
||||
description: string | null;
|
||||
expiresAt: Timestamp | null;
|
||||
id: Generated<string>;
|
||||
key: Buffer;
|
||||
password: string | null;
|
||||
showExif: Generated<boolean>;
|
||||
type: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface SmartInfo {
|
||||
assetId: string;
|
||||
objects: string[] | null;
|
||||
smartInfoTextSearchableColumn: Generated<string>;
|
||||
tags: string[] | null;
|
||||
}
|
||||
|
||||
export interface SmartSearch {
|
||||
assetId: string;
|
||||
embedding: string;
|
||||
}
|
||||
|
||||
export interface SocketIoAttachments {
|
||||
created_at: Generated<Timestamp | null>;
|
||||
id: Generated<Int8>;
|
||||
payload: Buffer | null;
|
||||
}
|
||||
|
||||
export interface SystemConfig {
|
||||
key: string;
|
||||
value: string | null;
|
||||
}
|
||||
|
||||
export interface SystemMetadata {
|
||||
key: string;
|
||||
value: Json;
|
||||
}
|
||||
|
||||
export interface TagAsset {
|
||||
assetsId: string;
|
||||
tagsId: string;
|
||||
}
|
||||
|
||||
export interface Tags {
|
||||
color: string | null;
|
||||
createdAt: Generated<Timestamp>;
|
||||
id: Generated<string>;
|
||||
parentId: string | null;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
userId: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface TagsClosure {
|
||||
id_ancestor: string;
|
||||
id_descendant: string;
|
||||
}
|
||||
|
||||
export interface UserMetadata {
|
||||
key: string;
|
||||
userId: string;
|
||||
value: Json;
|
||||
}
|
||||
|
||||
export interface Users {
|
||||
createdAt: Generated<Timestamp>;
|
||||
deletedAt: Timestamp | null;
|
||||
email: string;
|
||||
id: Generated<string>;
|
||||
isAdmin: Generated<boolean>;
|
||||
name: Generated<string>;
|
||||
oauthId: Generated<string>;
|
||||
password: Generated<string>;
|
||||
profileChangedAt: Generated<Timestamp>;
|
||||
profileImagePath: Generated<string>;
|
||||
quotaSizeInBytes: Int8 | null;
|
||||
quotaUsageInBytes: Generated<Int8>;
|
||||
shouldChangePassword: Generated<boolean>;
|
||||
status: Generated<string>;
|
||||
storageLabel: string | null;
|
||||
updatedAt: Generated<Timestamp>;
|
||||
}
|
||||
|
||||
export interface VectorsPgVectorIndexStat {
|
||||
idx_growing: ArrayType<Int8> | null;
|
||||
idx_indexing: boolean | null;
|
||||
idx_options: string | null;
|
||||
idx_sealed: ArrayType<Int8> | null;
|
||||
idx_size: Int8 | null;
|
||||
idx_status: string | null;
|
||||
idx_tuples: Int8 | null;
|
||||
idx_write: Int8 | null;
|
||||
indexname: string | null;
|
||||
indexrelid: number | null;
|
||||
tablename: string | null;
|
||||
tablerelid: number | null;
|
||||
}
|
||||
|
||||
export interface DB {
|
||||
activity: Activity;
|
||||
albums: Albums;
|
||||
albums_assets_assets: AlbumsAssetsAssets;
|
||||
albums_shared_users_users: AlbumsSharedUsersUsers;
|
||||
api_keys: ApiKeys;
|
||||
asset_faces: AssetFaces;
|
||||
asset_files: AssetFiles;
|
||||
asset_job_status: AssetJobStatus;
|
||||
asset_stack: AssetStack;
|
||||
assets: Assets;
|
||||
audit: Audit;
|
||||
exif: Exif;
|
||||
face_search: FaceSearch;
|
||||
geodata_places: GeodataPlaces;
|
||||
libraries: Libraries;
|
||||
memories: Memories;
|
||||
memories_assets_assets: MemoriesAssetsAssets;
|
||||
migrations: Migrations;
|
||||
move_history: MoveHistory;
|
||||
naturalearth_countries: NaturalearthCountries;
|
||||
partners: Partners;
|
||||
person: Person;
|
||||
sessions: Sessions;
|
||||
shared_link__asset: SharedLinkAsset;
|
||||
shared_links: SharedLinks;
|
||||
smart_info: SmartInfo;
|
||||
smart_search: SmartSearch;
|
||||
socket_io_attachments: SocketIoAttachments;
|
||||
system_config: SystemConfig;
|
||||
system_metadata: SystemMetadata;
|
||||
tag_asset: TagAsset;
|
||||
tags: Tags;
|
||||
tags_closure: TagsClosure;
|
||||
user_metadata: UserMetadata;
|
||||
users: Users;
|
||||
'vectors.pg_vector_index_stat': VectorsPgVectorIndexStat;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddTimeBucketIndices1734574016301 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX idx_local_date_time_month ON public.assets ((date_trunc('MONTH', "localDateTime" at time zone 'UTC') at time zone 'UTC'))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX idx_local_date_time ON public.assets ((("localDateTime" at time zone 'UTC')::date))`,
|
||||
);
|
||||
await queryRunner.query(`DROP INDEX "IDX_day_of_month"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_month"`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX idx_local_date_time_month`);
|
||||
await queryRunner.query(`DROP INDEX idx_local_date_time`);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_day_of_month" ON assets (EXTRACT(DAY FROM "localDateTime" AT TIME ZONE 'UTC'))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_month" ON assets (EXTRACT(MONTH FROM "localDateTime" AT TIME ZONE 'UTC'))`,
|
||||
);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,641 +1,268 @@
|
||||
-- NOTE: This file is auto generated by ./sql-generator
|
||||
|
||||
-- SearchRepository.searchMetadata
|
||||
SELECT DISTINCT
|
||||
"distinctAlias"."asset_id" AS "ids_asset_id",
|
||||
"distinctAlias"."asset_fileCreatedAt"
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"stack"."id" AS "stack_id",
|
||||
"stack"."ownerId" AS "stack_ownerId",
|
||||
"stack"."primaryAssetId" AS "stack_primaryAssetId",
|
||||
"stackedAssets"."id" AS "stackedAssets_id",
|
||||
"stackedAssets"."deviceAssetId" AS "stackedAssets_deviceAssetId",
|
||||
"stackedAssets"."ownerId" AS "stackedAssets_ownerId",
|
||||
"stackedAssets"."libraryId" AS "stackedAssets_libraryId",
|
||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||
"stackedAssets"."type" AS "stackedAssets_type",
|
||||
"stackedAssets"."status" AS "stackedAssets_status",
|
||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||
"stackedAssets"."updatedAt" AS "stackedAssets_updatedAt",
|
||||
"stackedAssets"."deletedAt" AS "stackedAssets_deletedAt",
|
||||
"stackedAssets"."fileCreatedAt" AS "stackedAssets_fileCreatedAt",
|
||||
"stackedAssets"."localDateTime" AS "stackedAssets_localDateTime",
|
||||
"stackedAssets"."fileModifiedAt" AS "stackedAssets_fileModifiedAt",
|
||||
"stackedAssets"."isFavorite" AS "stackedAssets_isFavorite",
|
||||
"stackedAssets"."isArchived" AS "stackedAssets_isArchived",
|
||||
"stackedAssets"."isExternal" AS "stackedAssets_isExternal",
|
||||
"stackedAssets"."isOffline" AS "stackedAssets_isOffline",
|
||||
"stackedAssets"."checksum" AS "stackedAssets_checksum",
|
||||
"stackedAssets"."duration" AS "stackedAssets_duration",
|
||||
"stackedAssets"."isVisible" AS "stackedAssets_isVisible",
|
||||
"stackedAssets"."livePhotoVideoId" AS "stackedAssets_livePhotoVideoId",
|
||||
"stackedAssets"."originalFileName" AS "stackedAssets_originalFileName",
|
||||
"stackedAssets"."sidecarPath" AS "stackedAssets_sidecarPath",
|
||||
"stackedAssets"."stackId" AS "stackedAssets_stackId",
|
||||
"stackedAssets"."duplicateId" AS "stackedAssets_duplicateId"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id"
|
||||
LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId"
|
||||
LEFT JOIN "assets" "stackedAssets" ON "stackedAssets"."stackId" = "stack"."id"
|
||||
AND ("stackedAssets"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
(
|
||||
"asset"."fileCreatedAt" >= $1
|
||||
AND "exifInfo"."lensModel" = $2
|
||||
AND 1 = 1
|
||||
AND "asset"."ownerId" IN ($3)
|
||||
AND 1 = 1
|
||||
AND (
|
||||
"asset"."isFavorite" = $4
|
||||
AND "asset"."isArchived" = $5
|
||||
)
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
) "distinctAlias"
|
||||
ORDER BY
|
||||
"distinctAlias"."asset_fileCreatedAt" DESC,
|
||||
"asset_id" ASC
|
||||
LIMIT
|
||||
101
|
||||
select
|
||||
"assets".*
|
||||
from
|
||||
"assets"
|
||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"assets"."fileCreatedAt" >= $1
|
||||
and "exif"."lensModel" = $2
|
||||
and "assets"."ownerId" = any ($3::uuid [])
|
||||
and "assets"."isFavorite" = $4
|
||||
and "assets"."isArchived" = $5
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"assets"."fileCreatedAt" desc
|
||||
limit
|
||||
$6
|
||||
offset
|
||||
$7
|
||||
|
||||
-- SearchRepository.searchRandom
|
||||
SELECT DISTINCT
|
||||
"distinctAlias"."asset_id" AS "ids_asset_id",
|
||||
"distinctAlias"."asset_id"
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"stack"."id" AS "stack_id",
|
||||
"stack"."ownerId" AS "stack_ownerId",
|
||||
"stack"."primaryAssetId" AS "stack_primaryAssetId",
|
||||
"stackedAssets"."id" AS "stackedAssets_id",
|
||||
"stackedAssets"."deviceAssetId" AS "stackedAssets_deviceAssetId",
|
||||
"stackedAssets"."ownerId" AS "stackedAssets_ownerId",
|
||||
"stackedAssets"."libraryId" AS "stackedAssets_libraryId",
|
||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||
"stackedAssets"."type" AS "stackedAssets_type",
|
||||
"stackedAssets"."status" AS "stackedAssets_status",
|
||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||
"stackedAssets"."updatedAt" AS "stackedAssets_updatedAt",
|
||||
"stackedAssets"."deletedAt" AS "stackedAssets_deletedAt",
|
||||
"stackedAssets"."fileCreatedAt" AS "stackedAssets_fileCreatedAt",
|
||||
"stackedAssets"."localDateTime" AS "stackedAssets_localDateTime",
|
||||
"stackedAssets"."fileModifiedAt" AS "stackedAssets_fileModifiedAt",
|
||||
"stackedAssets"."isFavorite" AS "stackedAssets_isFavorite",
|
||||
"stackedAssets"."isArchived" AS "stackedAssets_isArchived",
|
||||
"stackedAssets"."isExternal" AS "stackedAssets_isExternal",
|
||||
"stackedAssets"."isOffline" AS "stackedAssets_isOffline",
|
||||
"stackedAssets"."checksum" AS "stackedAssets_checksum",
|
||||
"stackedAssets"."duration" AS "stackedAssets_duration",
|
||||
"stackedAssets"."isVisible" AS "stackedAssets_isVisible",
|
||||
"stackedAssets"."livePhotoVideoId" AS "stackedAssets_livePhotoVideoId",
|
||||
"stackedAssets"."originalFileName" AS "stackedAssets_originalFileName",
|
||||
"stackedAssets"."sidecarPath" AS "stackedAssets_sidecarPath",
|
||||
"stackedAssets"."stackId" AS "stackedAssets_stackId",
|
||||
"stackedAssets"."duplicateId" AS "stackedAssets_duplicateId"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id"
|
||||
LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId"
|
||||
LEFT JOIN "assets" "stackedAssets" ON "stackedAssets"."stackId" = "stack"."id"
|
||||
AND ("stackedAssets"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
(
|
||||
"asset"."fileCreatedAt" >= $1
|
||||
AND "exifInfo"."lensModel" = $2
|
||||
AND 1 = 1
|
||||
AND "asset"."ownerId" IN ($3)
|
||||
AND 1 = 1
|
||||
AND (
|
||||
"asset"."isFavorite" = $4
|
||||
AND "asset"."isArchived" = $5
|
||||
select
|
||||
"assets".*
|
||||
from
|
||||
"assets"
|
||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"assets"."fileCreatedAt" >= $1
|
||||
and "exif"."lensModel" = $2
|
||||
and "assets"."ownerId" = any ($3::uuid [])
|
||||
and "assets"."isFavorite" = $4
|
||||
and "assets"."isArchived" = $5
|
||||
and "assets"."deletedAt" is null
|
||||
and "assets"."id" < $6
|
||||
order by
|
||||
"assets"."id"
|
||||
limit
|
||||
$7
|
||||
)
|
||||
AND "asset"."id" > $6
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
) "distinctAlias"
|
||||
ORDER BY
|
||||
"distinctAlias"."asset_id" ASC,
|
||||
"asset_id" ASC
|
||||
LIMIT
|
||||
100
|
||||
SELECT DISTINCT
|
||||
"distinctAlias"."asset_id" AS "ids_asset_id",
|
||||
"distinctAlias"."asset_id"
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"stack"."id" AS "stack_id",
|
||||
"stack"."ownerId" AS "stack_ownerId",
|
||||
"stack"."primaryAssetId" AS "stack_primaryAssetId",
|
||||
"stackedAssets"."id" AS "stackedAssets_id",
|
||||
"stackedAssets"."deviceAssetId" AS "stackedAssets_deviceAssetId",
|
||||
"stackedAssets"."ownerId" AS "stackedAssets_ownerId",
|
||||
"stackedAssets"."libraryId" AS "stackedAssets_libraryId",
|
||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||
"stackedAssets"."type" AS "stackedAssets_type",
|
||||
"stackedAssets"."status" AS "stackedAssets_status",
|
||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||
"stackedAssets"."updatedAt" AS "stackedAssets_updatedAt",
|
||||
"stackedAssets"."deletedAt" AS "stackedAssets_deletedAt",
|
||||
"stackedAssets"."fileCreatedAt" AS "stackedAssets_fileCreatedAt",
|
||||
"stackedAssets"."localDateTime" AS "stackedAssets_localDateTime",
|
||||
"stackedAssets"."fileModifiedAt" AS "stackedAssets_fileModifiedAt",
|
||||
"stackedAssets"."isFavorite" AS "stackedAssets_isFavorite",
|
||||
"stackedAssets"."isArchived" AS "stackedAssets_isArchived",
|
||||
"stackedAssets"."isExternal" AS "stackedAssets_isExternal",
|
||||
"stackedAssets"."isOffline" AS "stackedAssets_isOffline",
|
||||
"stackedAssets"."checksum" AS "stackedAssets_checksum",
|
||||
"stackedAssets"."duration" AS "stackedAssets_duration",
|
||||
"stackedAssets"."isVisible" AS "stackedAssets_isVisible",
|
||||
"stackedAssets"."livePhotoVideoId" AS "stackedAssets_livePhotoVideoId",
|
||||
"stackedAssets"."originalFileName" AS "stackedAssets_originalFileName",
|
||||
"stackedAssets"."sidecarPath" AS "stackedAssets_sidecarPath",
|
||||
"stackedAssets"."stackId" AS "stackedAssets_stackId",
|
||||
"stackedAssets"."duplicateId" AS "stackedAssets_duplicateId"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id"
|
||||
LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId"
|
||||
LEFT JOIN "assets" "stackedAssets" ON "stackedAssets"."stackId" = "stack"."id"
|
||||
AND ("stackedAssets"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
union all
|
||||
(
|
||||
"asset"."fileCreatedAt" >= $1
|
||||
AND "exifInfo"."lensModel" = $2
|
||||
AND 1 = 1
|
||||
AND "asset"."ownerId" IN ($3)
|
||||
AND 1 = 1
|
||||
AND (
|
||||
"asset"."isFavorite" = $4
|
||||
AND "asset"."isArchived" = $5
|
||||
select
|
||||
"assets".*
|
||||
from
|
||||
"assets"
|
||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"assets"."fileCreatedAt" >= $8
|
||||
and "exif"."lensModel" = $9
|
||||
and "assets"."ownerId" = any ($10::uuid [])
|
||||
and "assets"."isFavorite" = $11
|
||||
and "assets"."isArchived" = $12
|
||||
and "assets"."deletedAt" is null
|
||||
and "assets"."id" > $13
|
||||
order by
|
||||
"assets"."id"
|
||||
limit
|
||||
$14
|
||||
)
|
||||
AND "asset"."id" < $6
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
) "distinctAlias"
|
||||
ORDER BY
|
||||
"distinctAlias"."asset_id" ASC,
|
||||
"asset_id" ASC
|
||||
LIMIT
|
||||
100
|
||||
|
||||
-- SearchRepository.searchSmart
|
||||
START TRANSACTION
|
||||
SET
|
||||
LOCAL vectors.hnsw_ef_search = 200;
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"stack"."id" AS "stack_id",
|
||||
"stack"."ownerId" AS "stack_ownerId",
|
||||
"stack"."primaryAssetId" AS "stack_primaryAssetId",
|
||||
"stackedAssets"."id" AS "stackedAssets_id",
|
||||
"stackedAssets"."deviceAssetId" AS "stackedAssets_deviceAssetId",
|
||||
"stackedAssets"."ownerId" AS "stackedAssets_ownerId",
|
||||
"stackedAssets"."libraryId" AS "stackedAssets_libraryId",
|
||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||
"stackedAssets"."type" AS "stackedAssets_type",
|
||||
"stackedAssets"."status" AS "stackedAssets_status",
|
||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||
"stackedAssets"."updatedAt" AS "stackedAssets_updatedAt",
|
||||
"stackedAssets"."deletedAt" AS "stackedAssets_deletedAt",
|
||||
"stackedAssets"."fileCreatedAt" AS "stackedAssets_fileCreatedAt",
|
||||
"stackedAssets"."localDateTime" AS "stackedAssets_localDateTime",
|
||||
"stackedAssets"."fileModifiedAt" AS "stackedAssets_fileModifiedAt",
|
||||
"stackedAssets"."isFavorite" AS "stackedAssets_isFavorite",
|
||||
"stackedAssets"."isArchived" AS "stackedAssets_isArchived",
|
||||
"stackedAssets"."isExternal" AS "stackedAssets_isExternal",
|
||||
"stackedAssets"."isOffline" AS "stackedAssets_isOffline",
|
||||
"stackedAssets"."checksum" AS "stackedAssets_checksum",
|
||||
"stackedAssets"."duration" AS "stackedAssets_duration",
|
||||
"stackedAssets"."isVisible" AS "stackedAssets_isVisible",
|
||||
"stackedAssets"."livePhotoVideoId" AS "stackedAssets_livePhotoVideoId",
|
||||
"stackedAssets"."originalFileName" AS "stackedAssets_originalFileName",
|
||||
"stackedAssets"."sidecarPath" AS "stackedAssets_sidecarPath",
|
||||
"stackedAssets"."stackId" AS "stackedAssets_stackId",
|
||||
"stackedAssets"."duplicateId" AS "stackedAssets_duplicateId"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id"
|
||||
LEFT JOIN "asset_stack" "stack" ON "stack"."id" = "asset"."stackId"
|
||||
LEFT JOIN "assets" "stackedAssets" ON "stackedAssets"."stackId" = "stack"."id"
|
||||
AND ("stackedAssets"."deletedAt" IS NULL)
|
||||
INNER JOIN "smart_search" "search" ON "search"."assetId" = "asset"."id"
|
||||
WHERE
|
||||
(
|
||||
"asset"."fileCreatedAt" >= $1
|
||||
AND "exifInfo"."lensModel" = $2
|
||||
AND 1 = 1
|
||||
AND 1 = 1
|
||||
AND (
|
||||
"asset"."isFavorite" = $3
|
||||
AND "asset"."isArchived" = $4
|
||||
)
|
||||
AND "asset"."ownerId" IN ($5)
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"search"."embedding" <= > $6 ASC
|
||||
LIMIT
|
||||
201
|
||||
COMMIT
|
||||
select
|
||||
"assets".*
|
||||
from
|
||||
"assets"
|
||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
||||
inner join "smart_search" on "assets"."id" = "smart_search"."assetId"
|
||||
where
|
||||
"assets"."fileCreatedAt" >= $1
|
||||
and "exif"."lensModel" = $2
|
||||
and "assets"."ownerId" = any ($3::uuid [])
|
||||
and "assets"."isFavorite" = $4
|
||||
and "assets"."isArchived" = $5
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
smart_search.embedding <= > $6::vector
|
||||
limit
|
||||
$7
|
||||
offset
|
||||
$8
|
||||
|
||||
-- SearchRepository.searchDuplicates
|
||||
WITH
|
||||
"cte" AS (
|
||||
SELECT
|
||||
"asset"."duplicateId" AS "duplicateId",
|
||||
"search"."assetId" AS "assetId",
|
||||
"search"."embedding" <= > $1 AS "distance"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
INNER JOIN "smart_search" "search" ON "search"."assetId" = "asset"."id"
|
||||
WHERE
|
||||
(
|
||||
"asset"."ownerId" IN ($2)
|
||||
AND "asset"."id" != $3
|
||||
AND "asset"."isVisible" = $4
|
||||
AND "asset"."type" = $5
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
"search"."embedding" <= > $1 ASC
|
||||
LIMIT
|
||||
64
|
||||
with
|
||||
"cte" as (
|
||||
select
|
||||
"assets"."id" as "assetId",
|
||||
"assets"."duplicateId",
|
||||
smart_search.embedding <= > $1::vector as "distance"
|
||||
from
|
||||
"assets"
|
||||
inner join "smart_search" on "assets"."id" = "smart_search"."assetId"
|
||||
where
|
||||
"assets"."ownerId" = any ($2::uuid [])
|
||||
and "assets"."deletedAt" is null
|
||||
and "assets"."isVisible" = $3
|
||||
and "assets"."type" = $4
|
||||
and "assets"."id" != $5::uuid
|
||||
order by
|
||||
smart_search.embedding <= > $6::vector
|
||||
limit
|
||||
$7
|
||||
)
|
||||
SELECT
|
||||
res.*
|
||||
FROM
|
||||
"cte" "res"
|
||||
WHERE
|
||||
res.distance <= $6
|
||||
select
|
||||
*
|
||||
from
|
||||
"cte"
|
||||
where
|
||||
"cte"."distance" <= $8
|
||||
|
||||
-- SearchRepository.searchFaces
|
||||
START TRANSACTION
|
||||
SET
|
||||
LOCAL vectors.hnsw_ef_search = 100;
|
||||
WITH
|
||||
"cte" AS (
|
||||
SELECT
|
||||
"faces"."id" AS "id",
|
||||
"faces"."assetId" AS "assetId",
|
||||
"faces"."personId" AS "personId",
|
||||
"faces"."imageWidth" AS "imageWidth",
|
||||
"faces"."imageHeight" AS "imageHeight",
|
||||
"faces"."boundingBoxX1" AS "boundingBoxX1",
|
||||
"faces"."boundingBoxY1" AS "boundingBoxY1",
|
||||
"faces"."boundingBoxX2" AS "boundingBoxX2",
|
||||
"faces"."boundingBoxY2" AS "boundingBoxY2",
|
||||
"faces"."sourceType" AS "sourceType",
|
||||
"search"."embedding" <= > $1 AS "distance"
|
||||
FROM
|
||||
"asset_faces" "faces"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "faces"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
INNER JOIN "face_search" "search" ON "search"."faceId" = "faces"."id"
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($2)
|
||||
ORDER BY
|
||||
"search"."embedding" <= > $1 ASC
|
||||
LIMIT
|
||||
64
|
||||
with
|
||||
"cte" as (
|
||||
select
|
||||
"asset_faces"."id",
|
||||
"asset_faces"."personId",
|
||||
face_search.embedding <= > $1::vector as "distance"
|
||||
from
|
||||
"asset_faces"
|
||||
inner join "assets" on "assets"."id" = "asset_faces"."assetId"
|
||||
inner join "face_search" on "face_search"."faceId" = "asset_faces"."id"
|
||||
where
|
||||
"assets"."ownerId" = any ($2::uuid [])
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
face_search.embedding <= > $3::vector
|
||||
limit
|
||||
$4
|
||||
)
|
||||
SELECT
|
||||
res.*
|
||||
FROM
|
||||
"cte" "res"
|
||||
WHERE
|
||||
res.distance <= $3
|
||||
ORDER BY
|
||||
res.distance ASC
|
||||
COMMIT
|
||||
select
|
||||
*
|
||||
from
|
||||
"cte"
|
||||
where
|
||||
"cte"."distance" <= $5
|
||||
|
||||
-- SearchRepository.searchPlaces
|
||||
SELECT
|
||||
"geoplaces"."id" AS "geoplaces_id",
|
||||
"geoplaces"."name" AS "geoplaces_name",
|
||||
"geoplaces"."longitude" AS "geoplaces_longitude",
|
||||
"geoplaces"."latitude" AS "geoplaces_latitude",
|
||||
"geoplaces"."countryCode" AS "geoplaces_countryCode",
|
||||
"geoplaces"."admin1Code" AS "geoplaces_admin1Code",
|
||||
"geoplaces"."admin2Code" AS "geoplaces_admin2Code",
|
||||
"geoplaces"."admin1Name" AS "geoplaces_admin1Name",
|
||||
"geoplaces"."admin2Name" AS "geoplaces_admin2Name",
|
||||
"geoplaces"."alternateNames" AS "geoplaces_alternateNames",
|
||||
"geoplaces"."modificationDate" AS "geoplaces_modificationDate"
|
||||
FROM
|
||||
"geodata_places" "geoplaces"
|
||||
WHERE
|
||||
select
|
||||
*
|
||||
from
|
||||
"geodata_places"
|
||||
where
|
||||
f_unaccent (name) %>> f_unaccent ($1)
|
||||
OR f_unaccent ("admin2Name") %>> f_unaccent ($1)
|
||||
OR f_unaccent ("admin1Name") %>> f_unaccent ($1)
|
||||
OR f_unaccent ("alternateNames") %>> f_unaccent ($1)
|
||||
ORDER BY
|
||||
COALESCE(f_unaccent (name) <->>> f_unaccent ($1), 0.1) + COALESCE(
|
||||
f_unaccent ("admin2Name") <->>> f_unaccent ($1),
|
||||
or f_unaccent ("admin2Name") %>> f_unaccent ($2)
|
||||
or f_unaccent ("admin1Name") %>> f_unaccent ($3)
|
||||
or f_unaccent ("alternateNames") %>> f_unaccent ($4)
|
||||
order by
|
||||
coalesce(f_unaccent (name) <->>> f_unaccent ($5), 0.1) + coalesce(
|
||||
f_unaccent ("admin2Name") <->>> f_unaccent ($6),
|
||||
0.1
|
||||
) + COALESCE(
|
||||
f_unaccent ("admin1Name") <->>> f_unaccent ($1),
|
||||
) + coalesce(
|
||||
f_unaccent ("admin1Name") <->>> f_unaccent ($7),
|
||||
0.1
|
||||
) + COALESCE(
|
||||
f_unaccent ("alternateNames") <->>> f_unaccent ($1),
|
||||
) + coalesce(
|
||||
f_unaccent ("alternateNames") <->>> f_unaccent ($8),
|
||||
0.1
|
||||
) ASC
|
||||
LIMIT
|
||||
20
|
||||
)
|
||||
limit
|
||||
$9
|
||||
|
||||
-- SearchRepository.getAssetsByCity
|
||||
WITH RECURSIVE
|
||||
cte AS (
|
||||
with recursive
|
||||
"cte" as (
|
||||
(
|
||||
SELECT
|
||||
city,
|
||||
select
|
||||
"city",
|
||||
"assetId"
|
||||
FROM
|
||||
exif
|
||||
INNER JOIN assets ON exif."assetId" = assets.id
|
||||
WHERE
|
||||
"ownerId" = ANY ($1::uuid [])
|
||||
AND "isVisible" = $2
|
||||
AND "isArchived" = $3
|
||||
AND type = $4
|
||||
ORDER BY
|
||||
city
|
||||
LIMIT
|
||||
1
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"assets"."ownerId" = any ($1::uuid [])
|
||||
and "assets"."isVisible" = $2
|
||||
and "assets"."isArchived" = $3
|
||||
and "assets"."type" = $4
|
||||
and "assets"."deletedAt" is null
|
||||
order by
|
||||
"city"
|
||||
limit
|
||||
$5
|
||||
)
|
||||
UNION ALL
|
||||
SELECT
|
||||
l.city,
|
||||
l."assetId"
|
||||
FROM
|
||||
cte c,
|
||||
LATERAL (
|
||||
SELECT
|
||||
city,
|
||||
union all
|
||||
(
|
||||
select
|
||||
"l"."city",
|
||||
"l"."assetId"
|
||||
from
|
||||
"cte"
|
||||
inner join lateral (
|
||||
select
|
||||
"city",
|
||||
"assetId"
|
||||
FROM
|
||||
exif
|
||||
INNER JOIN assets ON exif."assetId" = assets.id
|
||||
WHERE
|
||||
city > c.city
|
||||
AND "ownerId" = ANY ($1::uuid [])
|
||||
AND "isVisible" = $2
|
||||
AND "isArchived" = $3
|
||||
AND type = $4
|
||||
ORDER BY
|
||||
city
|
||||
LIMIT
|
||||
1
|
||||
) l
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"assets"."ownerId" = any ($6::uuid [])
|
||||
and "assets"."isVisible" = $7
|
||||
and "assets"."isArchived" = $8
|
||||
and "assets"."type" = $9
|
||||
and "assets"."deletedAt" is null
|
||||
and "exif"."city" > "cte"."city"
|
||||
order by
|
||||
"city"
|
||||
limit
|
||||
$10
|
||||
) as "l" on true
|
||||
)
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"exif"."assetId" AS "exif_assetId",
|
||||
"exif"."description" AS "exif_description",
|
||||
"exif"."exifImageWidth" AS "exif_exifImageWidth",
|
||||
"exif"."exifImageHeight" AS "exif_exifImageHeight",
|
||||
"exif"."fileSizeInByte" AS "exif_fileSizeInByte",
|
||||
"exif"."orientation" AS "exif_orientation",
|
||||
"exif"."dateTimeOriginal" AS "exif_dateTimeOriginal",
|
||||
"exif"."modifyDate" AS "exif_modifyDate",
|
||||
"exif"."timeZone" AS "exif_timeZone",
|
||||
"exif"."latitude" AS "exif_latitude",
|
||||
"exif"."longitude" AS "exif_longitude",
|
||||
"exif"."projectionType" AS "exif_projectionType",
|
||||
"exif"."city" AS "exif_city",
|
||||
"exif"."livePhotoCID" AS "exif_livePhotoCID",
|
||||
"exif"."autoStackId" AS "exif_autoStackId",
|
||||
"exif"."state" AS "exif_state",
|
||||
"exif"."country" AS "exif_country",
|
||||
"exif"."make" AS "exif_make",
|
||||
"exif"."model" AS "exif_model",
|
||||
"exif"."lensModel" AS "exif_lensModel",
|
||||
"exif"."fNumber" AS "exif_fNumber",
|
||||
"exif"."focalLength" AS "exif_focalLength",
|
||||
"exif"."iso" AS "exif_iso",
|
||||
"exif"."exposureTime" AS "exif_exposureTime",
|
||||
"exif"."profileDescription" AS "exif_profileDescription",
|
||||
"exif"."colorspace" AS "exif_colorspace",
|
||||
"exif"."bitsPerSample" AS "exif_bitsPerSample",
|
||||
"exif"."rating" AS "exif_rating",
|
||||
"exif"."fps" AS "exif_fps"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
INNER JOIN "exif" "exif" ON "exif"."assetId" = "asset"."id"
|
||||
INNER JOIN cte ON asset.id = cte."assetId"
|
||||
ORDER BY
|
||||
exif.city
|
||||
|
||||
-- SearchRepository.getCountries
|
||||
SELECT DISTINCT
|
||||
ON ("exif"."country") "exif"."country" AS "country"
|
||||
FROM
|
||||
"exif" "exif"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($1)
|
||||
AND "exif"."country" != ''
|
||||
AND "exif"."country" IS NOT NULL
|
||||
)
|
||||
select
|
||||
"assets".*,
|
||||
to_jsonb("exif") as "exifInfo"
|
||||
from
|
||||
"assets"
|
||||
inner join "exif" on "assets"."id" = "exif"."assetId"
|
||||
inner join "cte" on "assets"."id" = "cte"."assetId"
|
||||
order by
|
||||
"exif"."city"
|
||||
|
||||
-- SearchRepository.getStates
|
||||
SELECT DISTINCT
|
||||
ON ("exif"."state") "exif"."state" AS "state"
|
||||
FROM
|
||||
"exif" "exif"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($1)
|
||||
AND "exif"."state" != ''
|
||||
AND "exif"."state" IS NOT NULL
|
||||
select distinct
|
||||
on ("state") "state"
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"ownerId" = any ($1::uuid [])
|
||||
and "isVisible" = $2
|
||||
and "deletedAt" is null
|
||||
and "state" is not null
|
||||
|
||||
-- SearchRepository.getCities
|
||||
SELECT DISTINCT
|
||||
ON ("exif"."city") "exif"."city" AS "city"
|
||||
FROM
|
||||
"exif" "exif"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($1)
|
||||
AND "exif"."city" != ''
|
||||
AND "exif"."city" IS NOT NULL
|
||||
select distinct
|
||||
on ("city") "city"
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"ownerId" = any ($1::uuid [])
|
||||
and "isVisible" = $2
|
||||
and "deletedAt" is null
|
||||
and "city" is not null
|
||||
|
||||
-- SearchRepository.getCameraMakes
|
||||
SELECT DISTINCT
|
||||
ON ("exif"."make") "exif"."make" AS "make"
|
||||
FROM
|
||||
"exif" "exif"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($1)
|
||||
AND "exif"."make" != ''
|
||||
AND "exif"."make" IS NOT NULL
|
||||
select distinct
|
||||
on ("make") "make"
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"ownerId" = any ($1::uuid [])
|
||||
and "isVisible" = $2
|
||||
and "deletedAt" is null
|
||||
and "make" is not null
|
||||
|
||||
-- SearchRepository.getCameraModels
|
||||
SELECT DISTINCT
|
||||
ON ("exif"."model") "exif"."model" AS "model"
|
||||
FROM
|
||||
"exif" "exif"
|
||||
INNER JOIN "assets" "asset" ON "asset"."id" = "exif"."assetId"
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
WHERE
|
||||
"asset"."ownerId" IN ($1)
|
||||
AND "exif"."model" != ''
|
||||
AND "exif"."model" IS NOT NULL
|
||||
select distinct
|
||||
on ("model") "model"
|
||||
from
|
||||
"exif"
|
||||
inner join "assets" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"ownerId" = any ($1::uuid [])
|
||||
and "isVisible" = $2
|
||||
and "deletedAt" is null
|
||||
and "model" is not null
|
||||
|
||||
@ -1,79 +1,29 @@
|
||||
-- NOTE: This file is auto generated by ./sql-generator
|
||||
|
||||
-- ViewRepository.getUniqueOriginalPaths
|
||||
select distinct
|
||||
substring("assets"."originalPath", $1) as "directoryPath"
|
||||
from
|
||||
"assets"
|
||||
where
|
||||
"ownerId" = $2::uuid
|
||||
and "isVisible" = $3
|
||||
and "isArchived" = $4
|
||||
and "deletedAt" is null
|
||||
|
||||
-- ViewRepository.getAssetsByOriginalPath
|
||||
SELECT
|
||||
"asset"."id" AS "asset_id",
|
||||
"asset"."deviceAssetId" AS "asset_deviceAssetId",
|
||||
"asset"."ownerId" AS "asset_ownerId",
|
||||
"asset"."libraryId" AS "asset_libraryId",
|
||||
"asset"."deviceId" AS "asset_deviceId",
|
||||
"asset"."type" AS "asset_type",
|
||||
"asset"."status" AS "asset_status",
|
||||
"asset"."originalPath" AS "asset_originalPath",
|
||||
"asset"."thumbhash" AS "asset_thumbhash",
|
||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||
"asset"."createdAt" AS "asset_createdAt",
|
||||
"asset"."updatedAt" AS "asset_updatedAt",
|
||||
"asset"."deletedAt" AS "asset_deletedAt",
|
||||
"asset"."fileCreatedAt" AS "asset_fileCreatedAt",
|
||||
"asset"."localDateTime" AS "asset_localDateTime",
|
||||
"asset"."fileModifiedAt" AS "asset_fileModifiedAt",
|
||||
"asset"."isFavorite" AS "asset_isFavorite",
|
||||
"asset"."isArchived" AS "asset_isArchived",
|
||||
"asset"."isExternal" AS "asset_isExternal",
|
||||
"asset"."isOffline" AS "asset_isOffline",
|
||||
"asset"."checksum" AS "asset_checksum",
|
||||
"asset"."duration" AS "asset_duration",
|
||||
"asset"."isVisible" AS "asset_isVisible",
|
||||
"asset"."livePhotoVideoId" AS "asset_livePhotoVideoId",
|
||||
"asset"."originalFileName" AS "asset_originalFileName",
|
||||
"asset"."sidecarPath" AS "asset_sidecarPath",
|
||||
"asset"."stackId" AS "asset_stackId",
|
||||
"asset"."duplicateId" AS "asset_duplicateId",
|
||||
"exifInfo"."assetId" AS "exifInfo_assetId",
|
||||
"exifInfo"."description" AS "exifInfo_description",
|
||||
"exifInfo"."exifImageWidth" AS "exifInfo_exifImageWidth",
|
||||
"exifInfo"."exifImageHeight" AS "exifInfo_exifImageHeight",
|
||||
"exifInfo"."fileSizeInByte" AS "exifInfo_fileSizeInByte",
|
||||
"exifInfo"."orientation" AS "exifInfo_orientation",
|
||||
"exifInfo"."dateTimeOriginal" AS "exifInfo_dateTimeOriginal",
|
||||
"exifInfo"."modifyDate" AS "exifInfo_modifyDate",
|
||||
"exifInfo"."timeZone" AS "exifInfo_timeZone",
|
||||
"exifInfo"."latitude" AS "exifInfo_latitude",
|
||||
"exifInfo"."longitude" AS "exifInfo_longitude",
|
||||
"exifInfo"."projectionType" AS "exifInfo_projectionType",
|
||||
"exifInfo"."city" AS "exifInfo_city",
|
||||
"exifInfo"."livePhotoCID" AS "exifInfo_livePhotoCID",
|
||||
"exifInfo"."autoStackId" AS "exifInfo_autoStackId",
|
||||
"exifInfo"."state" AS "exifInfo_state",
|
||||
"exifInfo"."country" AS "exifInfo_country",
|
||||
"exifInfo"."make" AS "exifInfo_make",
|
||||
"exifInfo"."model" AS "exifInfo_model",
|
||||
"exifInfo"."lensModel" AS "exifInfo_lensModel",
|
||||
"exifInfo"."fNumber" AS "exifInfo_fNumber",
|
||||
"exifInfo"."focalLength" AS "exifInfo_focalLength",
|
||||
"exifInfo"."iso" AS "exifInfo_iso",
|
||||
"exifInfo"."exposureTime" AS "exifInfo_exposureTime",
|
||||
"exifInfo"."profileDescription" AS "exifInfo_profileDescription",
|
||||
"exifInfo"."colorspace" AS "exifInfo_colorspace",
|
||||
"exifInfo"."bitsPerSample" AS "exifInfo_bitsPerSample",
|
||||
"exifInfo"."rating" AS "exifInfo_rating",
|
||||
"exifInfo"."fps" AS "exifInfo_fps"
|
||||
FROM
|
||||
"assets" "asset"
|
||||
LEFT JOIN "exif" "exifInfo" ON "exifInfo"."assetId" = "asset"."id"
|
||||
WHERE
|
||||
(
|
||||
(
|
||||
"asset"."isVisible" = $1
|
||||
AND "asset"."isArchived" = $2
|
||||
AND "asset"."ownerId" = $3
|
||||
)
|
||||
AND (
|
||||
"asset"."originalPath" LIKE $4
|
||||
AND "asset"."originalPath" NOT LIKE $5
|
||||
)
|
||||
)
|
||||
AND ("asset"."deletedAt" IS NULL)
|
||||
ORDER BY
|
||||
regexp_replace("asset"."originalPath", '.*/(.+)', '\1') ASC
|
||||
select
|
||||
"assets".*,
|
||||
to_jsonb("exif") as "exifInfo"
|
||||
from
|
||||
"assets"
|
||||
left join "exif" on "assets"."id" = "exif"."assetId"
|
||||
where
|
||||
"ownerId" = $1::uuid
|
||||
and "isVisible" = $2
|
||||
and "isArchived" = $3
|
||||
and "deletedAt" is null
|
||||
and "originalPath" like $4
|
||||
and "originalPath" not like $5
|
||||
order by
|
||||
regexp_replace("assets"."originalPath", $6, $7) asc
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,48 +1,47 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Kysely } from 'kysely';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { DB } from 'src/db';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { AssetEntity, withExif } from 'src/entities/asset.entity';
|
||||
import { IViewRepository } from 'src/interfaces/view.interface';
|
||||
import { Brackets, Repository } from 'typeorm';
|
||||
import { asUuid } from 'src/utils/database';
|
||||
|
||||
export class ViewRepository implements IViewRepository {
|
||||
constructor(@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>) {}
|
||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
async getUniqueOriginalPaths(userId: string): Promise<string[]> {
|
||||
const results = await this.assetRepository
|
||||
.createQueryBuilder('asset')
|
||||
.where({
|
||||
isVisible: true,
|
||||
isArchived: false,
|
||||
ownerId: userId,
|
||||
})
|
||||
.select("DISTINCT substring(asset.originalPath FROM '^(.*/)[^/]*$')", 'directoryPath')
|
||||
.getRawMany();
|
||||
const results = await this.db
|
||||
.selectFrom('assets')
|
||||
.select((eb) => eb.fn<string>('substring', ['assets.originalPath', eb.val('^(.*/)[^/]*$')]).as('directoryPath'))
|
||||
.distinct()
|
||||
.where('ownerId', '=', asUuid(userId))
|
||||
.where('isVisible', '=', true)
|
||||
.where('isArchived', '=', false)
|
||||
.where('deletedAt', 'is', null)
|
||||
.execute();
|
||||
|
||||
return results.map((row: { directoryPath: string }) => row.directoryPath.replaceAll(/^\/|\/$/g, ''));
|
||||
return results.map((row) => row.directoryPath.replaceAll(/^\/|\/$/g, ''));
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] })
|
||||
async getAssetsByOriginalPath(userId: string, partialPath: string): Promise<AssetEntity[]> {
|
||||
const normalizedPath = partialPath.replaceAll(/^\/|\/$/g, '');
|
||||
const assets = await this.assetRepository
|
||||
.createQueryBuilder('asset')
|
||||
.where({
|
||||
isVisible: true,
|
||||
isArchived: false,
|
||||
ownerId: userId,
|
||||
})
|
||||
.leftJoinAndSelect('asset.exifInfo', 'exifInfo')
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where('asset.originalPath LIKE :likePath', { likePath: `%${normalizedPath}/%` }).andWhere(
|
||||
'asset.originalPath NOT LIKE :notLikePath',
|
||||
{ notLikePath: `%${normalizedPath}/%/%` },
|
||||
);
|
||||
}),
|
||||
)
|
||||
.orderBy(String.raw`regexp_replace(asset.originalPath, '.*/(.+)', '\1')`, 'ASC')
|
||||
.getMany();
|
||||
|
||||
return assets;
|
||||
return this.db
|
||||
.selectFrom('assets')
|
||||
.selectAll('assets')
|
||||
.$call(withExif)
|
||||
.where('ownerId', '=', asUuid(userId))
|
||||
.where('isVisible', '=', true)
|
||||
.where('isArchived', '=', false)
|
||||
.where('deletedAt', 'is', null)
|
||||
.where('originalPath', 'like', `%${normalizedPath}/%`)
|
||||
.where('originalPath', 'not like', `%${normalizedPath}/%/%`)
|
||||
.orderBy(
|
||||
(eb) => eb.fn('regexp_replace', ['assets.originalPath', eb.val('.*/(.+)'), eb.val(String.raw`\1`)]),
|
||||
'asc',
|
||||
)
|
||||
.execute() as any as Promise<AssetEntity[]>;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue