Date range aggregation #
A multi-bucket aggregation like
range, but for date
fields. Each bucket is a from/to period you name — “before the launch”,
“launch week”, “after” — which is the shape reporting questions
naturally take, rather than the uniform grid of
date_histogram.
How it works #
Bounds are epoch milliseconds: from accepts a number (or a numeric
string) and is inclusive, to is exclusive, and either may be omitted
for an open-ended period. Date strings like "2024-06-04" are not
parsed by the aggregation — convert them to epoch millis first (the
teaching examples below show the constants).
Every declared range produces exactly one bucket, in declaration
order, even when zero documents match. The bucket key is your label
verbatim, or — when omitted — the built form "<from>-<to>" with *
for unbounded sides and whole numbers rendered without a decimal tail
("*-1717459200000"). Documents missing the field are skipped unless
missing supplies a default epoch-millis value, which drops them into
whichever period covers it.
Example #
Split logs at a mid-June cutoff (epoch millis 1718534400000, i.e.
2024-06-16T10:40:00Z):
The teaching logs dataset ends on June 7, so that cutoff matches no
document — the query scope is empty and both buckets return
doc_count: 0, which is the point worth noting: declared ranges always
materialize. A split inside the data window behaves as you would
expect:
POST /logs/_search
{
"size": 0,
"aggs": {
"by_period": {
"date_range": {
"field": "date",
"ranges": [
{ "key": "early", "to": 1717459200000 },
{ "key": "late", "from": 1717459200000 }
]
}
}
}
}
1717459200000 is 2024-06-04T00:00:00Z; of the 150 teaching logs, 72
fall before it and 78 from it onward:
{
...
"aggregations": {
"by_period": {
"buckets": [
{ "key": "early", "doc_count": 72 },
{ "key": "late", "doc_count": 78 }
]
}
}
}
Use cases #
- Before/after an event. Split at the launch timestamp, the
incident time, or the migration cutover, and nest a
sumoravgper period to compare behavior across it. - Named reporting periods. Fiscal quarters, holiday windows, retention cohorts — periods with business names, not equal widths.
- Open-ended cohorts.
"before","between","ever since"map directly onto omittedfrom/tosides. - Missing-value handling.
missingfolds documents without the date field into a chosen period instead of silently dropping them from every bucket.
Parameters for date_range
#
field
(Required, string) Date field you wish to aggregate.ranges
(Required, object array) Buckets with optionalfrom/to(epoch millis numbers or numeric strings;frominclusive,toexclusive).keynames a bucket.missing
(Optional, number) Epoch-millis value substituted for documents without the field.format
(Optional, string) Date format for renderingkey_as_string. Accepted for compatibility; the engine builds keys from the bounds as described above.aggs
(Optional, object) Nested sub-aggregations, computed per bucket.
Related #
range— the numeric-field sibling.date_histogram— equal calendar buckets when you want a timeline rather than named periods.ip_range— bands and CIDR masks over IP fields.- Range query — filter documents by a date window instead of bucketing them.