Full-text search tìm kiếm trong text content với stemming (running → run), stop words removal, và relevance ranking.
- PostgreSQL built-in: tsvector là processed document representation (to_tsvector('english', 'The quick brown fox') → 'brown':3 'fox':4 'quick':2); tsquery là search query (to_tsquery('quick & fox')).
- GIN index trên tsvector column cho fast lookups: CREATE INDEX ON articles USING GIN(to_tsvector('english', content)).
- Ranking với ts_rank(tsvector, tsquery) trả về float score.
- Đủ cho moderate needs (< vài triệu documents, single language, không cần fuzzy matching).
- Elasticsearch: inverted index — mỗi term map đến list of documents chứa term đó, cực nhanh cho text search.
- Distributed, horizontal scaling, advanced relevance scoring (BM25 algorithm), rich query DSL (fuzzy, phrase, wildcard, geospatial).
- Nhưng operational complexity cao: cần maintain Elasticsearch cluster, sync data từ primary DB.
- Typesense và Meilisearch: alternatives đơn giản hơn Elasticsearch — dễ setup, typo-tolerant search built-in, REST API friendly, tốt cho product search, documentation search.
- Quyết định: dùng PostgreSQL FTS nếu search là secondary feature và dataset nhỏ; Meilisearch/Typesense cho product search với good DX; Elasticsearch khi cần distributed, advanced analytics, log aggregation (ELK stack).