Sandboxed scripting — scripted_metric, script_fields, script_score

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.

Calendar October 7, 2026
Edit Edit this page