Sandboxed scripting — scripted_metric, script_fields, script_score #
Scripts landed across the whole request path — the engine runs the
examples from the Elasticsearch docs unmodified. The engine is Rhai
rather than Painless, but doc['x'].value, _score and
params.<name> mean what they mean there.
Aggregations.
scripted_metric
runs your own four-phase map/reduce — init_script, map_script,
combine_script, reduce_script — with per-segment states folded at the
end. The single-value metric aggs (sum, avg, min, max,
cardinality) accept a script in place of a field
(
details),
and pipeline aggregations keep their buckets_path arithmetic.
The hits themselves.
script_fields computes
extra values per returned hit at fetch time — nothing indexed, _source
untouched, results under fields as arrays:
POST /sales/_search
{
"size": 3,
"query": { "match_all": {} },
"script_fields": {
"doubled": { "script": "doc['amount'].value * 2" }
}
}
Scoring, filtering, sorting. The scripted queries wrap a query and replace its score, filter by predicate, or re-sort the page by a computed key:
POST /sales/_search
{
"query": {
"script_score": {
"query": { "match": { "field": "type", "query": "hat" } },
"script": "_score * doc['qty'].value"
}
}
}
script_score ranks the real candidate window — a high-scoring hit
outside the first page still wins — and _script sort re-sorts the
returned page, with the computed keys echoed per hit.
Everything runs in a sandbox: a per-script operation cap (a runaway loop
is cut off with a named error), no host IO — no filesystem, network, or
clock — and score tampering inside a script (_score = 99) stays local
to that evaluation. Builds without the scripting feature reject script
nodes explicitly rather than ignoring them. The full language reference —
scoping, params, the MovingFunctions.* spellings in pipelines — is
here.