Traditional keyword search fails users who know what they want but don't know the exact words. AI-powered semantic search understands intent, enabling queries like "budget-friendly lodging near the beach" to match results mentioning "affordable coastal vacation rentals."
The Problem with Keyword Search
SQL LIKE queries match exact text:
SELECT * FROM products WHERE name ILIKE '%beach%';
-- Misses: "oceanfront", "coastal", "seaside"Semantic search matches by meaning.
Setting Up pgvector on Supabase
CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE products ADD COLUMN embedding vector(1536);
CREATE INDEX products_embedding_idx ON products
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);Embedding Your Data
When a product is created or updated, generate its embedding:
async function generateAndStoreEmbedding(productId: string, text: string) {
const { data } = await openai.embeddings.create({
model: 'text-embedding-ada-002',
input: text
});
await supabase
.from('products')
.update({ embedding: data[0].embedding })
.eq('id', productId);
}The Search Function
CREATE OR REPLACE FUNCTION semantic_search(
query_embedding vector(1536),
similarity_threshold float,
match_count int
)
RETURNS TABLE (id uuid, name text, similarity float)
LANGUAGE plpgsql AS $$
BEGIN
RETURN QUERY
SELECT id, name, 1 - (embedding <=> query_embedding) AS similarity
FROM products
WHERE 1 - (embedding <=> query_embedding) > similarity_threshold
ORDER BY similarity DESC
LIMIT match_count;
END;
$$;Hybrid Search: Best of Both Worlds
For production, combine semantic and keyword search:
- If semantic score > 0.85: use semantic results only.
- If 0.70-0.85: merge with keyword results, ranked by combined score.
- Below 0.70: fall back to keyword search.
Result: After implementing semantic search on one of our e-commerce projects, product discovery increased by 34% and zero-result searches dropped from 18% to 3%.

