From 8083328f2da1b0deaa0adac263a5a5c32439bef6 Mon Sep 17 00:00:00 2001 From: Claudio Date: Sun, 17 May 2026 23:22:29 +0200 Subject: [PATCH] fix(filters): make path:folder query recursive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit filtersToQ emitted `path:` for any non-root folder, but PhotoPrism's `path:` operator is exact-by-default — so picking the "2024" node in the folder tree returned zero hits when all photos lived in date-stamped sub-folders (`2024/01`, `2024/02`, …). PP's indexer always nests photos under YYYY/MM, so every year-level folder was empty in the timeline. PhotoPrism supports a trailing `*` wildcard, so emit `path:"*"` instead: path:"2024*" → matches `2024`, `2024/01`, `2024/02/...`, … path:"2024/01*" → matches `2024/01` plus descendants — still correct for a leaf folder. Confirmed against the M0 instance: picking 2024 now returns the full year's photos; 2024/01 still returns its direct contents. --- web/src/lib/stores/filters.svelte.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/web/src/lib/stores/filters.svelte.ts b/web/src/lib/stores/filters.svelte.ts index 40f7ab0..4212eb5 100644 --- a/web/src/lib/stores/filters.svelte.ts +++ b/web/src/lib/stores/filters.svelte.ts @@ -97,8 +97,20 @@ export function filtersToQ(f: FilterState = filters): string { // express "exact root match" (path:"" / path:/ both fall back to "no // filter"), so we leave the server query unfiltered and let the // timeline post-filter to `Path === ''` client-side. + // + // For any non-root folder we want EVERY photo under that subtree, not + // just photos whose `photo_path` is an exact match. PhotoPrism's + // `path:` operator is exact-by-default but supports a trailing `*` + // wildcard: + // path:"2024" → matches only photos directly at `2024/` (none, + // if all files live in date-stamped sub-folders) + // path:"2024*" → matches `2024`, `2024/01`, `2024/02/...`, etc. + // path:"2024/01*" → matches `2024/01` plus descendants — still + // correct for a leaf folder. + // Always append `*` so internal tree nodes return the union of all + // descendant photos and leaves keep returning their direct contents. if (f.folderPath && f.folderPath !== '/') { - parts.push(`path:${quoteIfNeeded(f.folderPath)}`); + parts.push(`path:${quoteIfNeeded(f.folderPath + '*')}`); } if (f.search) parts.push(quoteIfNeeded(f.search)); return parts.join(' ');