ADR-004: PostgreSQL Full-Text Search
Status: Accepted — still in force. The Meilisearch provider and the search_documents copy table were deleted 2026-10-01 (migration 20261001221307_DropSearchDocuments); chapters.search_vector (trigger-maintained) is the only index.
Date: 2024-12
Context
Need search across chapter content. Options:
- PostgreSQL FTS
- Elasticsearch
- Algolia/Typesense
- LIKE queries
Decision
Use PostgreSQL Full-Text Search with tsvector and GIN indexes.
Implementation
Chapter.PlainTextstores extracted textChapter.SearchVector(tsvector) auto-generated- GIN index on SearchVector
- English config for stemming
Query:
SELECT ... FROM chaptersWHERE search_vector @@ plainto_tsquery('english', @query)ORDER BY ts_rank_cd(search_vector, plainto_tsquery('english', @query)) DESCConsequences
Pros
- No external service dependency
- Built into PostgreSQL
- Good enough for MVP scale
- No additional infrastructure
Cons
- Limited ranking sophistication
- Single language config per column
- No fuzzy matching by default
Notes
- May add pg_trgm for fuzzy title/author search
- Elasticsearch migration possible if needed at scale