Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 185 additions & 24 deletions _aggregations/bucket/date-range.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,134 @@

# Date range aggregations

The `date_range` aggregation is conceptually the same as the `range` aggregation, except that it lets you perform date math.
For example, you can get all documents from the last 10 days. To make the date more readable, include the format with a `format` parameter:
Use the `date_range` aggregation to group documents into buckets defined by date boundaries. It behaves like the numeric `range` aggregation, but accepts date math in addition to [ISO-8601](https://www.iso.org/iso-8601-date-and-time-format.html) dates and epoch milliseconds.

- `from` is inclusive.
- `to` is exclusive.
- You can omit `from` or `to` to create an open-ended bucket.
- Date math supports rounding, for example `now-7d/d` (start of the day, seven days ago).

## Parameters

The following is a table of parameters accepted by date range aggregations:

| Parameter | Required | Description |
| --- | --- | --- |
| `field` | Yes | The date field to aggregate on. |
| `ranges`| Yes | The non-empty array of range objects. Each object must specify at least one boundary, `from` and/or `to`. |
| `ranges[].from` | One of `from` or `to` is required | Lower inclusive bound. |
| `ranges[].to` | One of `from` or `to` is required | Upper exclusive bound. |
| `ranges[].key`| No | The label for the bucket.|
| `format`| No | Controls the `*_as_string` fields in the response, for example `yyyy-MM-dd`. |
| `time_zone` | No | The IANA zone or UTC offset used when evaluating date math/rounding, for example `Europe/Dublin`, `+01:00`. |
| `keyed` | No | If `true`, returns an object keyed by `key` instead of an array. |
| `missing` | No | Substitute value for documents where the field is missing. |


### Accepted values for `from` and `to`

- ISO-8601 strings: `"2025-10-01T00:00:00Z"`, `"2025-10-01"`.
- Date math: `"now-7d/d"`, `"now+1M/M"`, `"2025-09-01||/M"`.
- Epoch milliseconds: `1756684800000`.

If a date string omits components, the missing parts are filled with defaults. For example, `"2025-10"` is treated as the start of October 2025.
{: .note}

## Example: Three sliding windows

The following example produces three buckets, last 7 days, previous 7 days, and older, using date math and `yyyy-MM-dd` output `format`.

```json
GET my-index/_search
{
"size": 0,
"aggs": {
"by_range": {
"date_range": {
"field": "@timestamp",
"format": "yyyy-MM-dd",
"ranges": [
{ "from": "now-7d/d", "to": "now+1d/d", "key": "last_7d" },
{ "from": "now-14d/d", "to": "now-7d/d", "key": "prev_7d" },
{ "to": "now-14d/d", "key": "older" }
]
}
}
}
}
```
{% include copy-curl.html %}

Example response:

```json
"aggregations": {
"by_range": {
"buckets": [
{
"key": "older",
"to": 1758067200000,
"to_as_string": "2025-09-17",
"doc_count": 1
},
{
"key": "prev_7d",
"from": 1758067200000,
"from_as_string": "2025-09-17",
"to": 1758672000000,
"to_as_string": "2025-09-24",
"doc_count": 2
},
{
"key": "last_7d",
"from": 1758672000000,
"from_as_string": "2025-09-24",
"to": 1759363200000,
"to_as_string": "2025-10-02",
"doc_count": 2
}
]
}
}
```

## Example: Last 10 days bucket with custom string format

Creates a single bucket that covers the last 10 calendar days. It starts at the beginning of the day 10 days ago (`now-10d/d`) and ends at the beginning of tomorrow (`now+1d/d`, exclusive). The `format` only affects the `*_as_string` fields in the response, not document matching.

```json
GET my-index/_search
{
"size": 0,
"aggs": {
"last_10_days": {
"date_range": {
"field": "@timestamp",
"format": "yyyy-MM",
"ranges": [ { "from": "now-10d/d", "to": "now+1d/d" } ]
}
}
}
}
```
{% include copy-curl.html %}

## Example: Keyed response and custom keys

Return an object keyed by your labels for easier downstream processing:

```json
GET opensearch_dashboards_sample_data_logs/_search
GET my-index/_search
{
"size": 0,
"aggs": {
"number_of_bytes": {
"keyed_ranges": {
"date_range": {
"field": "@timestamp",
"format": "MM-yyyy",
"keyed": true,
"ranges": [
{
"from": "now-10d/d",
"to": "now"
}
{ "from": "now-1d/d", "to": "now+1d/d", "key": "today" },
{ "to": "now-1d/d", "key": "before_today" }
]
}
}
Expand All @@ -34,23 +145,73 @@
```
{% include copy-curl.html %}

#### Example response
Example response:

```json
...
"aggregations" : {
"number_of_bytes" : {
"buckets" : [
{
"key" : "03-2021-03-2021",
"from" : 1.6145568E12,
"from_as_string" : "03-2021",
"to" : 1.615451329043E12,
"to_as_string" : "03-2021",
"doc_count" : 0
"aggregations": {
"keyed_ranges": {
"buckets": {
"before_today": {
"to": 1759190400000,
"to_as_string": "2025-09-30T00:00:00.000Z",
"doc_count": 4
},
"today": {
"from": 1759190400000,
"from_as_string": "2025-09-30T00:00:00.000Z",
"to": 1759363200000,
"to_as_string": "2025-10-02T00:00:00.000Z",
"doc_count": 1
}
}
]
}
}
```

## Example: Epoch millis with a time zone

Check failure on line 171 in _aggregations/bucket/date-range.md

View workflow job for this annotation

GitHub Actions / style-job

[vale] reported by reviewdog 🐶 [OpenSearch.Spelling] Error: millis. If you are referencing a setting, variable, format, function, or repository, surround it with tic marks. Raw Output: {"message": "[OpenSearch.Spelling] Error: millis. If you are referencing a setting, variable, format, function, or repository, surround it with tic marks.", "location": {"path": "_aggregations/bucket/date-range.md", "range": {"start": {"line": 171, "column": 19}}}, "severity": "ERROR"}

When the field value is epoch millis, you can still provide `from`/`to` as numbers. See following request, `time_zone` affects date math and boundary evaluation:

Check failure on line 173 in _aggregations/bucket/date-range.md

View workflow job for this annotation

GitHub Actions / style-job

[vale] reported by reviewdog 🐶 [OpenSearch.Spelling] Error: millis. If you are referencing a setting, variable, format, function, or repository, surround it with tic marks. Raw Output: {"message": "[OpenSearch.Spelling] Error: millis. If you are referencing a setting, variable, format, function, or repository, surround it with tic marks.", "location": {"path": "_aggregations/bucket/date-range.md", "range": {"start": {"line": 173, "column": 31}}}, "severity": "ERROR"}

```json
GET my-index/_search
{
"size": 0,
"aggs": {
"local_ranges": {
"date_range": {
"field": "event_time",
"time_zone": "Europe/Dublin",
"format": "epoch_millis",
"ranges": [
{ "from": "1697328000000", "to": "1697932800000", "key": "week_sample" }
]
}
}
}
}
```
{% include copy-curl.html %}

## Example: Handling missing dates

Use `missing` to route documents without a value into a bucket by substituting a default:

```json
GET my-index/_search
{
"size": 0,
"aggs": {
"dated_or_undated": {
"date_range": {
"field": "@timestamp",
"missing": "1970-01-01",
"ranges": [
{ "to": "2000-01-01", "key": "undated_or_old" },
{ "from": "2000-01-01", "key": "dated_recent" }
]
}
}
}
}
}
```
```
{% include copy-curl.html %}
Loading