cleanup
parent
3817aec5b1
commit
32945a01b4
|
|
@ -279,7 +279,7 @@ const StringSimilarityFilterSchema = z
|
|||
})
|
||||
.meta({ id: 'StringSimilarityFilter' });
|
||||
|
||||
const SearchOrderSchema = z
|
||||
export const SearchOrderSchema = z
|
||||
.strictObject({
|
||||
field: SearchOrderFieldSchema.default(SearchOrderField.FileCreatedAt),
|
||||
direction: AssetOrderSchema.default(AssetOrder.Desc),
|
||||
|
|
@ -323,7 +323,7 @@ const SearchFilterBranchSchema = z
|
|||
})
|
||||
.meta({ id: 'SearchFilterBranch' });
|
||||
|
||||
const SearchFilterSchema = SearchFilterBranchSchema.extend({
|
||||
export const SearchFilterSchema = SearchFilterBranchSchema.extend({
|
||||
or: z.array(SearchFilterBranchSchema).min(1).optional(),
|
||||
}).meta({ id: 'SearchFilter' });
|
||||
|
||||
|
|
|
|||
|
|
@ -558,8 +558,8 @@ const FIELD_BACKING: Record<keyof Omit<SearchFilterBranch, 'or'>, Backing> = {
|
|||
};
|
||||
|
||||
function branchNeedsExifJoin(branch: SearchFilterBranch): boolean {
|
||||
for (const key of Object.keys(FIELD_BACKING) as (keyof typeof FIELD_BACKING)[]) {
|
||||
if (FIELD_BACKING[key] === 'asset_exif' && branch[key] !== undefined) {
|
||||
for (const key of Object.keys(branch) as (keyof typeof FIELD_BACKING)[]) {
|
||||
if (FIELD_BACKING[key] === 'asset_exif') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -598,8 +598,6 @@ function exifJoinRequired(filter: SearchFilter, orderField: SearchOrderField): b
|
|||
*/
|
||||
type AssetEB = ExpressionBuilder<DB, 'asset' | 'asset_exif'>;
|
||||
|
||||
// ---- EXISTS expression helpers (returned as Expression<SqlBool>) ----
|
||||
|
||||
function existsAlbumLink(eb: AssetEB, want: boolean): Expression<SqlBool> {
|
||||
const e = eb.exists((eb2) => eb2.selectFrom('album_asset').whereRef('album_asset.assetId', '=', 'asset.id'));
|
||||
return want ? e : eb.not(e);
|
||||
|
|
@ -665,8 +663,6 @@ function existsEncodedVideoPath(eb: AssetEB, f: StringFilter): Expression<SqlBoo
|
|||
return out;
|
||||
}
|
||||
|
||||
// ---- IdsFilter EXISTS helpers ----
|
||||
|
||||
type IdsKind = 'album' | 'person' | 'tag';
|
||||
|
||||
function idsAnyExists(eb: AssetEB, kind: IdsKind, ids: string[]): Expression<SqlBool> {
|
||||
|
|
@ -747,15 +743,13 @@ function pushIdsFilter(preds: Expression<SqlBool>[], eb: AssetEB, kind: IdsKind,
|
|||
preds.push(idsAnyExists(eb, kind, f.any));
|
||||
}
|
||||
if (f.all) {
|
||||
preds.push(idsAllExists(eb, kind, f.all));
|
||||
preds.push(f.all.length === 1 ? idsAnyExists(eb, kind, f.all) : idsAllExists(eb, kind, f.all));
|
||||
}
|
||||
if (f.none) {
|
||||
preds.push(eb.not(idsAnyExists(eb, kind, f.none)));
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Per-filter-family pushers ----
|
||||
|
||||
function pushIdEqNe(
|
||||
preds: Expression<SqlBool>[],
|
||||
eb: AssetEB,
|
||||
|
|
@ -975,15 +969,12 @@ function pushChecksum(preds: Expression<SqlBool>[], eb: AssetEB, f: StringFilter
|
|||
function buildBranchPredicates(eb: AssetEB, b: SearchFilterBranch): Expression<SqlBool>[] {
|
||||
const p: Expression<SqlBool>[] = [];
|
||||
|
||||
// id / libraryId
|
||||
pushIdEqNe(p, eb, 'asset.id', b.id);
|
||||
pushIdEqNe(p, eb, 'asset.libraryId', b.libraryId);
|
||||
|
||||
// enums
|
||||
pushEnum(p, eb, 'asset.type', b.type);
|
||||
pushEnum(p, eb, 'asset.visibility', b.visibility);
|
||||
|
||||
// bools on asset
|
||||
if (b.isFavorite) {
|
||||
p.push(eb('asset.isFavorite', '=', b.isFavorite.eq));
|
||||
}
|
||||
|
|
@ -997,7 +988,6 @@ function buildBranchPredicates(eb: AssetEB, b: SearchFilterBranch): Expression<S
|
|||
p.push(existsEncodedVideo(eb, b.isEncoded.eq));
|
||||
}
|
||||
|
||||
// membership presence
|
||||
if (b.hasAlbums) {
|
||||
p.push(existsAlbumLink(eb, b.hasAlbums.eq));
|
||||
}
|
||||
|
|
@ -1008,7 +998,6 @@ function buildBranchPredicates(eb: AssetEB, b: SearchFilterBranch): Expression<S
|
|||
p.push(existsTagLink(eb, b.hasTags.eq));
|
||||
}
|
||||
|
||||
// EXIF string columns (nullable)
|
||||
pushStringEqNeInNotIn(p, eb, 'asset_exif.city', b.city);
|
||||
pushStringEqNeInNotIn(p, eb, 'asset_exif.state', b.state);
|
||||
pushStringEqNeInNotIn(p, eb, 'asset_exif.country', b.country);
|
||||
|
|
@ -1016,27 +1005,22 @@ function buildBranchPredicates(eb: AssetEB, b: SearchFilterBranch): Expression<S
|
|||
pushStringEqNeInNotIn(p, eb, 'asset_exif.model', b.model);
|
||||
pushStringEqNeInNotIn(p, eb, 'asset_exif.lensModel', b.lensModel);
|
||||
|
||||
// StringPattern columns
|
||||
pushStringPattern(p, eb, 'asset_exif.description', b.description);
|
||||
pushStringPattern(p, eb, 'asset.originalFileName', b.originalFileName);
|
||||
pushStringPattern(p, eb, 'asset.originalPath', b.originalPath);
|
||||
|
||||
// ocr similarity (EXISTS over ocr_search — no top-level join)
|
||||
if (b.ocr) {
|
||||
p.push(existsOcrMatch(eb, b.ocr.matches));
|
||||
}
|
||||
|
||||
// numbers
|
||||
pushNumber(p, eb, 'asset_exif.rating', b.rating);
|
||||
pushNumber(p, eb, 'asset_exif.fileSizeInByte', b.fileSizeInBytes);
|
||||
|
||||
// dates
|
||||
pushDate(p, eb, 'asset.fileCreatedAt', b.takenAt);
|
||||
pushDate(p, eb, 'asset.createdAt', b.createdAt);
|
||||
pushDate(p, eb, 'asset.updatedAt', b.updatedAt);
|
||||
pushDate(p, eb, 'asset.deletedAt', b.trashedAt);
|
||||
|
||||
// IdsFilter — EXISTS-based, composable with OR
|
||||
if (b.albumIds) {
|
||||
pushIdsFilter(p, eb, 'album', b.albumIds);
|
||||
}
|
||||
|
|
@ -1047,10 +1031,8 @@ function buildBranchPredicates(eb: AssetEB, b: SearchFilterBranch): Expression<S
|
|||
pushIdsFilter(p, eb, 'tag', b.tagIds);
|
||||
}
|
||||
|
||||
// checksum (bytea, decoded from string on the wire)
|
||||
pushChecksum(p, eb, b.checksum);
|
||||
|
||||
// encodedVideoPath — EXISTS over asset_file with path predicate
|
||||
if (b.encodedVideoPath) {
|
||||
p.push(...existsEncodedVideoPath(eb, b.encodedVideoPath));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue