Hybrid Search

Hybrid Search

Combine vector similarity with full-text search for best-in-class retrieval. Get the semantic understanding of embeddings plus the precision of keyword matching.

What is Hybrid Search?

Hybrid search combines vector similarity (semantic meaning) with full-text search (keyword matching) to provide superior search results that understand both context and exact terms.

Vector Search Alone

  • ✓ Understands semantic meaning
  • ✓ Finds conceptually similar content
  • ✗ May miss exact keyword matches
  • ✗ Can return loosely related results

Full-Text Search Alone

  • ✓ Precise keyword matching
  • ✓ Fast for exact terms
  • ✗ No semantic understanding
  • ✗ Misses synonyms and context

Hybrid Search = Best of Both

  • Semantic understanding from vector embeddings
  • Precise keyword matching from full-text search
  • Weighted scoring to balance both approaches
  • Superior relevance and recall

Basic Hybrid Search

Setup Table

-- Create table with vector and text columns CREATE TABLE knowledge_base ( id SERIAL PRIMARY KEY, title TEXT, content TEXT, embedding vector(384), ts_vector tsvector ); -- Create indexes CREATE INDEX ON knowledge_base USING hnsw (embedding vector_l2_ops); CREATE INDEX ON knowledge_base USING gin (ts_vector); -- Insert data with embeddings and text index INSERT INTO knowledge_base (title, content, embedding, ts_vector) VALUES ( 'PostgreSQL Performance', 'Optimize queries with indexes and EXPLAIN', embed_text('Optimize queries with indexes and EXPLAIN'), to_tsvector('Optimize queries with indexes and EXPLAIN') );

Perform Hybrid Search

-- Hybrid search: 70% vector + 30% text SELECT * FROM hybrid_search( 'knowledge_base', -- table name 'content', -- text column 'embedding', -- vector column 'database optimization', -- query 10, -- limit 0.7, -- vector weight (70%) 0.3 -- text weight (30%) ); -- Returns: id, title, content, vector_score, text_score, hybrid_score

Reranking for Precision

Cross-Encoder Reranking

Cross-encoders jointly encode the query and each candidate for higher precision scoring.

-- Rerank search results with cross-encoder SELECT rerank_cross_encoder( 'What is PostgreSQL?', -- query ARRAY[ -- candidate documents 'PostgreSQL is a database', 'MySQL is also a database', 'Redis is a cache' ], 'ms-marco-MiniLM-L-6-v2', -- model 3 -- top_n ); -- Returns: -- idx | score -- -----+------- -- 0 | 0.945 (most relevant) -- 1 | 0.678 -- 2 | 0.123 (least relevant)

MMR (Maximal Marginal Relevance)

MMR balances relevance with diversity to avoid redundant results.

-- MMR reranking for diverse results SELECT * FROM mmr_rerank( 'knowledge_base', -- table 'embedding', -- vector column embed_text('database'), -- query vector 20, -- fetch top 20 candidates 5, -- return top 5 diverse results 0.7 -- lambda (0.7 = 70% relevance, 30% diversity) ); -- Returns: id, title, score, diversity

Best Practices

1. Tune Vector/Text Weights

Adjust the balance based on your use case:

  • 0.9/0.1 - Heavily semantic (concepts matter more than exact terms)
  • 0.7/0.3 - Balanced (default, works for most cases)
  • 0.5/0.5 - Equal weight (both semantic and keywords important)
  • 0.3/0.7 - Keyword-focused (exact terms critical)

2. Index Both Columns

-- Always index both for performance CREATE INDEX ON docs USING hnsw (embedding vector_l2_ops); CREATE INDEX ON docs USING gin (ts_vector);

3. Use Reranking for Top Results

Fetch 50-100 candidates with hybrid search, then rerank top 10-20 for best precision.