Cumulative cardinality aggregation

Cumulative cardinality aggregation #

A parent pipeline aggregation reporting a running total of a per-bucket distinct count — typically a cardinality metric — answering “how many unique values have been counted up to and including each bucket”.

"seen_so_far": {
  "cumulative_cardinality": { "buckets_path": "buyers" }
}

How it works #

cumulative_cardinality is declared inside the multi-bucket aggregation it decorates, next to the metric it consumes. The engine walks the finished buckets in order and attaches the running total of the referenced values under the pipeline’s own name — mechanically the same accumulation as cumulative_sum; only the intended input (a per-bucket distinct count) differs.

That framing matters for correctness: the engine adds up the per-bucket counts; it does not union the distinct value sets across buckets (no sketch merge happens between buckets). Two consequences:

  • Exact when buckets are disjoint — every distinct value appears in at most one bucket. Buckets keyed by the value itself (a terms agg over the same field you count distincts of), or one-off identifiers partitioned by period (unique order ids per day), are disjoint by construction.
  • It overcounts when a value recurs in several buckets. Per-day buyer counts accumulate to more than the true number of distinct buyers, because a buyer active on three days is counted three times. A quick executed example: per-bucket distinct counts 2, 2, 1 produce 2, 4, 5, while the true running union is 2, 3, 4.

Details verified against the engine:

  • buckets_path addresses a cardinality metric (or any single-value metric) in the same bucket; "_count" accumulates document counts.
  • A bucket whose metric is missing answers null and the running total freezes, exactly as cumulative_sum does.
  • The sibling placement also works: declared next to the bucket aggregation with buckets_path: "per_day>buyers", it returns a standalone buckets array (keys 0..n−1) with one value per consumed bucket.

Examples #

Read this one with the caveat above in mind. The teaching dataset sells exactly once per day, so every bucket’s buyers is 1 and seen_so_far climbs 1, 2, 3, … to 120 — while the whole index holds only 4 distinct merchants, each active in many buckets. The column is the accumulated per-day counts, not the running union.

Use cases #

  • Disjoint-cohort counters — bucket documents by a cohort key (first-purchase month, signup week) and count distinct customers per cohort: each customer belongs to exactly one bucket, so the running column is the exact customer count to date.
  • Unique-per-period identifiers — daily counts of distinct order or request ids, which by construction cannot span buckets, give an exact running volume of unique events.
  • Growth of a partitioned vocabulary — terms per day over write-once keys (new SKUs, new nodes joining a cluster) accumulate correctly because a new key’s first appearance is its only one.
  • A quick upper bound — even when values repeat across buckets, the column bounds the distinct count from above at every point, which can be enough for capacity signals.

Parameters for cumulative_cardinality #

  • buckets_path
    (Required, string) Path to a cardinality metric in the same bucket.
  • format
    (Optional, string) Output number format. Accepted for compatibility; not applied to the value in the current engine.
  • gap_policy
    (Optional, string) skip (default) or insert_zeros.
Calendar October 6, 2026
Edit Edit this page