SearchProvider interface with PostgreSQL FTS implementation #49
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#49
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Search v1 is PostgreSQL FTS behind an interface so an external engine can be added later without touching call sites (ADR 0010).
Scope
Define
SearchProvider(indexPage,removePage,search(query, {pondId?, labels?}, userId)) in the search module; implement the Postgres binding: generated weightedtsvectorcolumn (title A, labels B, body C;simple+ unaccent config) with GIN index onpage_content_cache,ts_headlinesnippets, permission filtering by joining the readable-page-id set;GET /searchendpoint;search:reindexCLI command.Acceptance criteria
page_content_cacheand is idempotentTechnical notes
page_content_cache).Dependencies
Depends on #35.
Size: ~1.5 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Implemented in
91dfccf(Claude Opus 4.8). Pipeline green (CI incl. all e2e packs; CD deploy Test → smoke → promote Int).Live-verified on Test: created a page "Zeppelin Umlaut Bäume …";
GET /search?q=Zeppelin&pondId=…returns it (title weight A), andGET /search?q=Baume&pondId=…also returns it — diacritic-insensitive matching ('Baume' finds 'Bäume') works live without theunaccentextension.Acceptance criteria
[](db test).normalizeForSearchfolds both the vector and the query (db test + live).page_content_cacheand is idempotent:search:reindexCLI; db test runsreindexAlltwice with identical results.Design notes
unaccentextension) so the schema-pushed test databases keep working; the GIN index lives only in the migration (a production perf optimization — correctness holds without it, which is why the db-tests pass on adb pushschema).search_vectoris maintained in two places with the same weighting: the api'sSearchProvider(title/label changes) and the collab persistence hook (content changes), both folding throughnormalizeForSearch.SearchProvideris an abstract-class DI token; swapping to Meilisearch/OpenSearch is a one-line provider change (ADR 0010).search:reindexis a CLI (instantiates the provider directly —tsx/esbuild does not emit the decorator metadata Nest DI needs).Next M4 issue: #50 (search UI) — already implemented.