Rescore

Rescore #

rescore re-ranks the top window of hits with a second query — an expensive precision pass (phrase, vector similarity, a narrow filter match) applied only where it can change the final page, instead of to every matching document.

POST /my-collection/_search

How it works #

Rescore is engine-native. When a request carries a rescore block, the collector widens its gather to max(from + size, window) candidates, the first-pass query ranks them, and the store layer then applies the rescore to the collected set (apply_rescore_to_result in lib/engine/src/store/layered/generic_reader.rs, blending in lib/engine/src/search/scorer/mod.rs):

  • Each hit INSIDE the window is scored by the rescore query and blended: new = query_weight × first_pass + rescore_query_weight × rescore. A window hit the rescore query does not match contributes 0 from the second term.
  • Hits OUTSIDE the window keep their first-pass score SCALED by query_weight — the weight applies to the whole result set, not just the window.
  • The full list is re-sorted so the re-scored window interleaves with the untouched tail, then truncated to from + size.

The blend is always the weighted sum above — the internal scorer chain also knows multiply/avg/max/min modes, but the request API exposes only total. One rescorer per request: the native dialect is a single object (the gateway rejects the array form with a 400).

Wire-form status: the ES-compatibility layer understands the Elasticsearch shape (window_size plus a nested query: {rescore_query, …} object), translates it to the native flat dialect, applies only the FIRST rescorer of an array, and enforces the validations — window below 10000, and collapse + rescore mutually exclusive. Through the Pizza gateway itself, send the native form below; the nested form is a parse error today, and the native path does not (yet) reject the collapse mix.

Examples #

Lift the request-log needle out of a match-all haystack: every logs document scores 1.0 on the first pass; the rescore adds three times the search match score to the top 50 — 1.0 × 1.0 + 3.0 × 2.566 ≈ 8.70 for the strongest matches, so the 25 GET /search requests jump above the other 145.

Shrink the window to 2 and only the two leading hits get the treatment — every other hit keeps 1.0 × query_weight. That boundary is the whole point of the feature: pay for the expensive query on 2 or 50 documents, never on all 150 (or 150 million).

Phrase precision on top of loose matching — base query wide, phrase rescore exact:

{
  "query": { "match": { "field": "text", "query": "wood fired pizza" } },
  "rescore": {
    "window": 10,
    "query": { "phrase": { "field": "text", "query": "wood fired" } },
    "query_weight": 0.7,
    "rescore_query_weight": 1.5
  },
  "size": 5
}

Use cases #

  • Vector precision pass. Text match for recall, vector similarity over the top 10 for order — Stage 4 of the hybrid pipeline.
  • Phrase tightening. Loose match recall with a phrase rescore so exact word order wins the top slots without punishing the recall underneath.
  • Boost a narrow signal. “Order by relevance, but let recent VIP activity win ties” — a filter-shaped rescore query over a small window is cheaper than scoring it for the whole corpus.
  • Bandwidth-guarded reranking. Keep the window at or just above from + size; anything larger spends second-pass score on hits the caller will never see.

Parameters for rescore #

  • window
    (Optional, integer, default: 10) How many top hits to re-score. The collector gathers at least max(from + size, window) candidates.
  • query
    (Required, object) The rescoring query — any query type, executed over the window; its score is blended into each in-window hit.
  • query_weight
    (Optional, float, default: 1.0) Weight of the first-pass score, for in-window blends and the outside-window scaling alike.
  • rescore_query_weight
    (Optional, float, default: 1.0) Weight of the rescore query’s score.

Notes #

  • retrieve (hybrid) requests cannot carry rescore — the gateway rejects the mix; use Stage 4 only with a plain query.
  • score_functions and rescore compose freely on one plain query (functions shape the first-pass score, rescore then blends the second).
  • An all-match_all pair makes the arithmetic easy to eyeball: base 1, rescore 1, so scores read as pure weights (5/15 in the conformance case above).
  • Hybrid search pipeline — rescore is Stage 4 of the retrieve → fuse → score_functions → rescore chain.
  • Sort and pagination — the other result-shaping half; rescore re-sorts by blended score, sort fixes the order outright.
  • Field collapsing — the third member of the result-shaping family; the ES-compat layer rejects the collapse + rescore mix.
  • vector query — the usual resident of the query slot for similarity rescoring.
Calendar October 6, 2026
Edit Edit this page