Scripted queries

Scripted queries #

Scripts in the search request: script_score to compute the score, a script predicate in a boolean filter, and a _script sort key. All run on Pizza’s sandboxed script engine (see the script language reference) — Rhai, not Painless, but the doc['x'].value, _score, params.<name> spellings run unmodified.

script_score — score by script #

Wrap a query; the script’s value replaces the score. The script sees _score (the wrapped query’s BM25 score), doc (the hit’s _source in doc-values shape) and params:

Ranking follows the script — the three hits come back in amount order, with _score equal to amount. A script that needs the base relevance:

Nested script_score wrappers chain: the inner script computes the score the outer script’s _score sees. An evaluation error fails the request with a message naming script_score.

script — filter by predicate #

The script query, a boolean predicate per document, in any clause position of a bool:

The script must evaluate to a boolean; anything else is a named error. Predicates apply to the collected window after the base query runs — post_filter-class semantics: the window is bounded by from + size (or collect_size when set), and aggregations are not narrowed. When you need aggs over the filtered set, add a range/term filter alongside the script (those execute inside the segment, narrowing everything). Deep per-segment script filtering is on the roadmap, demand-gated.

_script — sort key by script #

A sort clause whose key is computed per hit of the returned page — the same page-sized rule as script_fields:

At most one _script clause per request. Numbers compare numerically, strings lexicographically, and a script that returns nothing places per the missing policy. The computed key surfaces as the hit’s sort value. Page membership is decided by the preceding ranking — _script re-orders the page, it does not re-rank the whole candidate set.

The script_score function in score_functions #

Inside score_functions (function scoring), the script_score function form nests the script under "script", and combines through score_mode / boost_mode like the other functions:

Parameters for script_score #

  • query
    (Required, query) The wrapped query; its hits form the candidate window the script re-scores.
  • script
    (Required, string or object) The scoring script — an inline string or { "source": …, "params": … }. _score, doc and params are in scope; the script’s value replaces the score.
  • min_score
    (unsupported) Not implemented on the script_score query; thresholds on the computed score must be applied by the caller.

The script filter query takes a single script parameter in the same two forms, nested once more ({ "script": { "script": … } } — the double-nested form).

Use cases #

  • Business scoring. Rank by margin, inventory age or any stored number the text ranker cannot see — doc['amount'].value as the score, or _score * doc['qty'].value to blend relevance with volume (both playgrounds above).
  • Non-declarable predicates. A script filter in a bool expresses conditions no DSL clause covers — parity checks, cross-field arithmetic, threshold ratios — evaluated per document of the collected window.
  • Computed sort keys. The _script sort orders the returned page by a per-hit expression (price with VAT applied) without storing the derived value.
  • Custom function scoring. Inside score_functions, a script is one more decay-or-boost function, combined through score_mode / boost_mode with the others.
  • Pipeline scripts — the script language reference: syntax, sandbox limits, and the helper functions available on every scripting surface, this one included.
  • sort — field-based sorting; _script is its computed-key clause.
  • script_fields — the fetch-phase sibling: computed values returned per hit, page-sized like _script.
  • hybrid — the score_functions context where the script_score function form lives.

Notes and limits #

  • Cost: scripts evaluate per hit of the collected window — roughly 2–5 µs per hit per script, native. script_score widens collection to collect_size (default 10000) so the script ranks real candidates; the page is trimmed afterwards. The check for scripted queries on a non-script request costs ~17 ns (one tree walk), so the feature is free when unused.
  • Sandboxed: the same containment as every other script surface — operation cap (a runaway while true {} fails the request in milliseconds, never hangs), no host or network IO, bounded sizes.
  • _score and doc are per-eval copies: assigning to them inside a script changes nothing outside that one evaluation.
  • min_score on the script_score query is not implemented.
Calendar October 7, 2026
Edit Edit this page