Moving fn aggregation

Moving fn aggregation #

A parent pipeline aggregation computing a window statistic over the last N buckets’ metrics — MovingFunctions.max(values), MovingFunctions.sum(values), MovingFunctions.min(values) and friends, with the window sliding bucket by bucket.

"smooth": {
  "moving_fn": {
    "buckets_path": "revenue",
    "window": 3,
    "script": "MovingFunctions.max(values)"
  }
}

How it works #

moving_fn is declared inside the multi-bucket aggregation it decorates, next to the metric it consumes. After the buckets are built, the engine slides a trailing window over their values and, for each bucket, evaluates the script once with the window exposed as values — a floating-point array, oldest first, current bucket last. The script’s numeric result is attached to that bucket under the pipeline’s own name.

Details verified against the engine:

  • The window always ends at the current bucket and is truncated at the start of the series: the first bucket’s values holds one element, the second at most two.
  • window defaults to 5; 0 is treated as 1; a negative or fractional value is rejected when the request parses.
  • shift is accepted for compatibility but currently not applied — there is no way yet to offset the window forward or backward; it stays strictly trailing.
  • Gaps follow gap_policy: skip (default) leaves missing values out, so the window shrinks; insert_zeros contributes 0.0. A window left with no values at all answers null.
  • A script that fails to compile inserts nothing (the nested form) or returns no buckets (the sibling form); a runtime failure or a non-numeric result nulls that bucket’s value only.
  • A second, engine-specific placement also works: declaring moving_fn next to the bucket aggregation, with buckets_path: "per_day>revenue", returns a standalone buckets array (keys 0..n−1) with one value per consumed bucket.

Scripts are sandboxed Rhai with the MovingFunctions.* helpers built in — the full variable, operator and helper catalogue lives in pipeline scripts. moving_avg is the same aggregation with a fixed averaging script.

Examples #

Each bucket’s smooth is the largest daily revenue among that day and the two before it — a rolling peak. Swap the script for MovingFunctions.sum(values) to get a trailing 3-day total, or values.max() - values.min() for the spread inside the window.

Use cases #

  • Rolling envelope — max/min over a window draws the peak and floor lines capacity planning watches (peak daily load over the trailing week).
  • Windowed totals — MovingFunctions.sum(values) with window: 7 is “revenue over the last 7 buckets”, the trailing total dashboards prefer over cumulative-since-forever.
  • Stability bands — MovingFunctions.stdDev(values, MovingFunctions.unweightedAvg(values)) measures how wildly the series moves inside each window; a rising band precedes most incidents.
  • Custom window statistics — anything expressible as a script: median-ish values[len/2], first-minus-last, count-above-threshold (values.filter(|v| v > 100).len()).

Parameters for moving_fn #

  • buckets_path
    (Required, string) Path to the consumed metric in the same bucket.
  • script
    (Required, string) Window function over values, e.g. MovingFunctions.max(values) — see pipeline scripts.
  • window
    (Optional, integer, default: 5) Number of buckets in the sliding window; clamped to a minimum of 1.
  • gap_policy
    (Optional, string) skip (default) or insert_zeros.
  • shift
    (Optional, integer, default: 0) Accepted for compatibility; not yet applied — the window stays trailing.
  • moving_avg — the fixed-average specialization (sibling placement)
  • bucket_script — per-bucket arithmetic over sibling metrics, no window
  • pipeline scripts — the script language and the MovingFunctions helper catalogue
Calendar October 6, 2026
Edit Edit this page