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,docandparamsare in scope; the script’s value replaces the score.min_score
(unsupported) Not implemented on thescript_scorequery; 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'].valueas the score, or_score * doc['qty'].valueto blend relevance with volume (both playgrounds above). - Non-declarable predicates. A
scriptfilter in aboolexpresses conditions no DSL clause covers — parity checks, cross-field arithmetic, threshold ratios — evaluated per document of the collected window. - Computed sort keys. The
_scriptsort 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 throughscore_mode/boost_modewith the others.
Related #
- 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;_scriptis its computed-key clause.script_fields— the fetch-phase sibling: computed values returned per hit, page-sized like_script.hybrid— thescore_functionscontext where thescript_scorefunction form lives.
Notes and limits #
- Cost: scripts evaluate per hit of the collected window — roughly
2–5 µs per hit per script, native.
script_scorewidens collection tocollect_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. _scoreanddocare per-eval copies: assigning to them inside a script changes nothing outside that one evaluation.min_scoreon thescript_scorequery is not implemented.