Stage 1 — SQL LIKE
SELECT * FROM products WHERE name LIKE '%widget%'
Simple. Works for small datasets. Problems: cannot use indexes (leading wildcard), no relevance ranking, no typo tolerance. Use only for prototypes or very small datasets.
Stage 2 — Native full-text search
PostgreSQL: tsvector + tsquery with GIN indexes. MySQL: FULLTEXT indexes with MATCH ... AGAINST. Much faster than LIKE, with relevance ranking. No typo tolerance or semantic understanding.
-- PostgreSQL full-text
SELECT *, ts_rank(to_tsvector(name), query) AS rank
FROM products, to_tsquery('widget & blue') query
WHERE to_tsvector(name) @@ query
ORDER BY rank DESC;
Stage 3 — Elasticsearch / OpenSearch
When you need: fuzzy matching, autocomplete, faceted search, multi-language support, or search across millions of documents. Sync data from your primary DB to Elasticsearch via CDC or scheduled reindexing.
Stage 4 — Semantic / vector search
Embed both documents and queries with a text model. Search by cosine similarity instead of keyword overlap. Finds conceptually related results even when no keywords match. Combine with keyword search (hybrid retrieval) for best results.