Hybrid Search

Definition

Hybrid search combines two or more retrieval signals — most commonly sparse (lexical/term-based) and dense (semantic/embedding-based) — to produce results that outperform either approach alone.

The intuition: sparse retrieval excels at exact keyword matching; dense retrieval excels at semantic understanding. Their failure modes are largely complementary.

Erik Hatcher (MongoDB) offers a practitioner’s definition that widens the frame beyond sparse+dense: combining two or more search techniques to produce results better than any single technique alone. The operative word is better — which makes measurement a precondition rather than a follow-up, and yields the series mantra measure, tune, repeat. On this reading “hybrid” is a mindset of blending rather than a prescriptive recipe, and it retroactively covers the older practice of folding behavioral signals and learned rules into a query, not just fusing two ranked lists. See Survey of the Hybrid Search Landscape.

The rankability spectrum

Hatcher orders the available techniques by rankability — how readily the query-document relationship can be given a numeric score:

TechniqueRankability
Key/value matching (B-Tree, exact + range)None intrinsically — binary match; proximity can be computed
Vector searchGeometric distance; embedding model choice is the dominant relevancy factor
Lexical searchRichest — field weights, term and document frequencies, per-clause formulas

Why Combine?

Retrieval TypeStrengthsWeaknesses
Sparse (BM25/SPLADE)Exact terms, proper nouns, codesVocabulary mismatch, no synonyms
Dense (Bi-Encoder)Semantics, paraphrases, intentWeak on rare terms, slower
HybridBest of bothMore complex, harder to tune

Fusion Strategies

Reciprocal Rank Fusion (RRF)

Most common, parameter-free:

RRF_score(d) = Σ 1 / (k + rank_i(d))

where k=60 is a constant that smooths rank differences.

Advantages: No score normalization needed, robust, no training required.

Linear Score Combination

final_score = α × sparse_score + (1 − α) × dense_score

Requires score normalization (scores from different systems aren’t comparable). Skipping the normalization step is a live production failure mode, not a theoretical one — see the warning under Implementation in Elasticsearch below.

Re-ranking

Retrieve N candidates from each system → merge → re-rank with Cross-Encoder.

Learning-to-Rank Fusion

Treat each retriever’s score (BM25, cosine) as an input feature to a LambdaMART / LTR model trained on click feedback — the model learns the optimal combination, and decision trees handle missing scores when a document came from only one retriever. Metarank is an open-source secondary re-ranker built for exactly this; Interleaving provides the cold-start baseline ranking used to collect the initial click data.

Common Implementations

SPLADE + Bi-Encoder

  • SPLADE for learned sparse retrieval (term expansion)
  • Bi-Encoder (e.g., sentence-transformers) for dense semantic
  • Fusion: RRF or learned combiner

BM25 + Dense

  • BM25 for lexical baseline (no ML required)
  • Dense encoder for semantic lift
  • Popular in production (Elasticsearch, OpenSearch)

PostgreSQL (single datastore)

Vespa Hybrid

The measured zero-shot case, from Improving Zero-Shot Ranking with Vespa Hybrid Search - part two — tuned BM25 fused with a distilled 22M ColBERT reranker, min-max normalized and linearly weighted, across 13 BEIR datasets:

Average nDCG@10
BM25 alone0.453
ColBERT alone0.363
Hybrid0.481 (wins 12 of 13)

The instructive row is the middle one. The neural component loses to BM25 standalone and still improves the combination — fusion pays off because the two are wrong about different documents, not because the added retriever is better. On HotpotQA (0.298 vs 0.623) and FEVER (0.534 vs 0.751) ColBERT is far behind and the hybrid still edges past BM25. Do not screen a candidate retriever out of a hybrid on its standalone score.

The one loss, CLIMATE-FEVER, is a truncation artifact: 20.2-word average queries against a 32-wordpiece limit drove ColBERT to 0.067, and fusing near-noise drags the result below BM25 alone. A fusion is only as safe as its weakest branch on your query distribution.

Implementation in Elasticsearch

# Two-phase: BM25 + ELSER (sparse) or BM25 + dense
GET /products/_search
{
  "query": {
    "bool": {
      "should": [
        {"match": {"text": "query"}},           # BM25
        {"text_expansion": {                     # ELSER sparse
          "ml.tokens": {"model_id": ".elser_model_1", "model_text": "query"}
        }}
      ]
    }
  }
}

A bool/should merge sums raw scores — it does not normalize

In a bool query, a document matching several should clauses scores the sum of those clauses. The engine does not normalize across clauses; it adds whatever each one emits. So the effective ranking function above is BM25 + second_clause_score, on whatever scales those two happen to occupy.

The mismatch is starkest when the second clause is a bounded knn clause: BM25 is unbounded — it rises with term frequency, term rarity and shortness, with no ceiling — while cosine-derived vector scores sit in a narrow band typically well under 1. Summed, the unbounded branch can decide the ranking outright and the vector branch stops participating.

Do not read the example above as safe merely because both clauses are term-based. ELSER text_expansion scores are sums of learned term weights and are not bounded either, and two unbounded scores are still not two calibrated scores — they need normalizing just as much, only with a less dramatic failure when you skip it.

This fails silently: the query compiles, returns a single _score, and looks correct. Prefer the engine’s purpose-built hybrid query with a normalization pipeline (see OpenSearch), or normalize explicitly before weighting (Linear Score Combination).

Worked example and diagnostics: Hybrid Fusion Failure - BM25 Displacing Reference Documents.

Wormhole Vectors as Hybrid Bridge

Trey Grainger’s Wormhole Vectors concept extends hybrid search by identifying vectors that bridge multiple retrieval spaces (sparse, dense, behavioral). A document traverses from one space to another through these “wormhole” connections.

People

Semantic Boosting

Semantic Boosting is a two-phase alternative to RRF/RSF fusion: run vector search first, inject the results as boost clauses into a final lexical query. The output comes entirely from the lexical engine, so faceting, highlighting, and pagination work natively without extra merging.

Case Studies