Skip to content

Commit 0192fe7

Browse files
authored
Add documentation for calendar/fixed intervals (#41919)
Original PR missed documentation for the new calendar/fixed intervals. This adds the missing documentation
1 parent afba887 commit 0192fe7

File tree

1 file changed

+197
-87
lines changed

1 file changed

+197
-87
lines changed

docs/reference/aggregations/bucket/datehistogram-aggregation.asciidoc

Lines changed: 197 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -10,122 +10,194 @@ that here the interval can be specified using date/time expressions. Time-based
1010
data requires special support because time-based intervals are not always a
1111
fixed length.
1212

13-
==== Setting intervals
14-
15-
There seems to be no limit to the creativity we humans apply to setting our
16-
clocks and calendars. We've invented leap years and leap seconds, standard and
17-
daylight savings times, and timezone offsets of 30 or 45 minutes rather than a
18-
full hour. While these creations help keep us in sync with the cosmos and our
19-
environment, they can make specifying time intervals accurately a real challenge.
20-
The only universal truth our researchers have yet to disprove is that a
21-
millisecond is always the same duration, and a second is always 1000 milliseconds.
22-
Beyond that, things get complicated.
23-
24-
Generally speaking, when you specify a single time unit, such as 1 hour or 1 day, you
25-
are working with a _calendar interval_, but multiples, such as 6 hours or 3 days, are
26-
_fixed-length intervals_.
27-
28-
For example, a specification of 1 day (1d) from now is a calendar interval that
29-
means "at
30-
this exact time tomorrow" no matter the length of the day. A change to or from
31-
daylight savings time that results in a 23 or 25 hour day is compensated for and the
32-
specification of "this exact time tomorrow" is maintained. But if you specify 2 or
33-
more days, each day must be of the same fixed duration (24 hours). In this case, if
34-
the specified interval includes the change to or from daylight savings time, the
35-
interval will end an hour sooner or later than you expect.
36-
37-
There are similar differences to consider when you specify single versus multiple
38-
minutes or hours. Multiple time periods longer than a day are not supported.
39-
40-
Here are the valid time specifications and their meanings:
13+
==== Calendar and Fixed intervals
4114

42-
milliseconds (ms) ::
43-
Fixed length interval; supports multiples.
15+
When configuring a date histogram aggregation, the interval can be specified
16+
in two manners: calendar-aware time intervals, and fixed time intervals.
4417

45-
seconds (s) ::
46-
1000 milliseconds; fixed length interval (except for the last second of a
47-
minute that contains a leap-second, which is 2000ms long); supports multiples.
18+
Calendar-aware intervals understand that daylight savings changes the length
19+
of specific days, months have different amounts of days, and leap seconds can
20+
be tacked onto a particular year.
4821

49-
minutes (m) ::
22+
Fixed intervals are, by contrast, always multiples of SI units and do not change
23+
based on calendaring context.
24+
25+
[NOTE]
26+
.Combined `interval` field is deprecated
27+
==================================
28+
deprecated[7.2, `interval` field is deprecated] Historically both calendar and fixed
29+
intervals were configured in a single `interval` field, which led to confusing
30+
semantics. Specifying `1d` would be assumed as a calendar-aware time,
31+
whereas `2d` would be interpreted as fixed time. To get "one day" of fixed time,
32+
the user would need to specify the next smaller unit (in this case, `24h`).
33+
34+
This combined behavior was often unknown to users, and even when knowledgeable about
35+
the behavior it was difficult to use and confusing.
36+
37+
This behavior has been deprecated in favor of two new, explicit fields: `calendar_interval`
38+
and `fixed_interval`.
39+
40+
By forcing a choice between calendar and intervals up front, the semantics of the interval
41+
are clear to the user immediately and there is no ambiguity. The old `interval` field
42+
will be removed in the future.
43+
==================================
44+
45+
===== Calendar Intervals
46+
47+
Calendar-aware intervals are configured with the `calendar_interval` parameter.
48+
Calendar intervals can only be specified in "singular" quantities of the unit
49+
(`1d`, `1M`, etc). Multiples, such as `2d`, are not supported and will throw an exception.
50+
51+
The accepted units for calendar intervals are:
52+
53+
minute (`m`, `1m`) ::
5054
All minutes begin at 00 seconds.
5155

52-
* One minute (1m) is the interval between 00 seconds of the first minute and 00
56+
One minute is the interval between 00 seconds of the first minute and 00
5357
seconds of the following minute in the specified timezone, compensating for any
54-
intervening leap seconds, so that the number of minutes and seconds past the
55-
hour is the same at the start and end.
56-
* Multiple minutes (__n__m) are intervals of exactly 60x1000=60,000 milliseconds
57-
each.
58+
intervening leap seconds, so that the number of minutes and seconds past the
59+
hour is the same at the start and end.
5860

59-
hours (h) ::
61+
hours (`h`, `1h`) ::
6062
All hours begin at 00 minutes and 00 seconds.
6163

62-
* One hour (1h) is the interval between 00:00 minutes of the first hour and 00:00
64+
One hour (1h) is the interval between 00:00 minutes of the first hour and 00:00
6365
minutes of the following hour in the specified timezone, compensating for any
6466
intervening leap seconds, so that the number of minutes and seconds past the hour
65-
is the same at the start and end.
66-
* Multiple hours (__n__h) are intervals of exactly 60x60x1000=3,600,000 milliseconds
67-
each.
67+
is the same at the start and end.
6868

69-
days (d) ::
69+
70+
days (`d`, `1d`) ::
7071
All days begin at the earliest possible time, which is usually 00:00:00
7172
(midnight).
7273

73-
* One day (1d) is the interval between the start of the day and the start of
74+
One day (1d) is the interval between the start of the day and the start of
7475
of the following day in the specified timezone, compensating for any intervening
7576
time changes.
76-
* Multiple days (__n__d) are intervals of exactly 24x60x60x1000=86,400,000
77-
milliseconds each.
7877

79-
weeks (w) ::
78+
week (`w`, `1w`) ::
8079

81-
* One week (1w) is the interval between the start day_of_week:hour:minute:second
82-
and the same day of the week and time of the following week in the specified
80+
One week is the interval between the start day_of_week:hour:minute:second
81+
and the same day of the week and time of the following week in the specified
8382
timezone.
84-
* Multiple weeks (__n__w) are not supported.
8583

86-
months (M) ::
84+
month (`M`, `1M`) ::
8785

88-
* One month (1M) is the interval between the start day of the month and time of
86+
One month is the interval between the start day of the month and time of
8987
day and the same day of the month and time of the following month in the specified
9088
timezone, so that the day of the month and time of day are the same at the start
9189
and end.
92-
* Multiple months (__n__M) are not supported.
9390

94-
quarters (q) ::
91+
quarter (`q`, `1q`) ::
9592

96-
* One quarter (1q) is the interval between the start day of the month and
93+
One quarter (1q) is the interval between the start day of the month and
9794
time of day and the same day of the month and time of day three months later,
9895
so that the day of the month and time of day are the same at the start and end. +
99-
* Multiple quarters (__n__q) are not supported.
10096

101-
years (y) ::
97+
year (`y`, `1y`) ::
10298

103-
* One year (1y) is the interval between the start day of the month and time of
104-
day and the same day of the month and time of day the following year in the
99+
One year (1y) is the interval between the start day of the month and time of
100+
day and the same day of the month and time of day the following year in the
105101
specified timezone, so that the date and time are the same at the start and end. +
106-
* Multiple years (__n__y) are not supported.
107102

108-
NOTE:
109-
In all cases, when the specified end time does not exist, the actual end time is
110-
the closest available time after the specified end.
103+
===== Calendar Interval Examples
104+
As an example, here is an aggregation requesting bucket intervals of a month in calendar time:
111105

112-
Widely distributed applications must also consider vagaries such as countries that
113-
start and stop daylight savings time at 12:01 A.M., so end up with one minute of
114-
Sunday followed by an additional 59 minutes of Saturday once a year, and countries
115-
that decide to move across the international date line. Situations like
116-
that can make irregular timezone offsets seem easy.
106+
[source,js]
107+
--------------------------------------------------
108+
POST /sales/_search?size=0
109+
{
110+
"aggs" : {
111+
"sales_over_time" : {
112+
"date_histogram" : {
113+
"field" : "date",
114+
"calendar_interval" : "month"
115+
}
116+
}
117+
}
118+
}
119+
--------------------------------------------------
120+
// CONSOLE
121+
// TEST[setup:sales]
117122

118-
As always, rigorous testing, especially around time-change events, will ensure
119-
that your time interval specification is
120-
what you intend it to be.
123+
If you attempt to use multiples of calendar units, the aggregation will fail because only
124+
singular calendar units are supported:
121125

122-
WARNING:
123-
To avoid unexpected results, all connected servers and clients must sync to a
124-
reliable network time service.
126+
[source,js]
127+
--------------------------------------------------
128+
POST /sales/_search?size=0
129+
{
130+
"aggs" : {
131+
"sales_over_time" : {
132+
"date_histogram" : {
133+
"field" : "date",
134+
"calendar_interval" : "2d"
135+
}
136+
}
137+
}
138+
}
139+
--------------------------------------------------
140+
// CONSOLE
141+
// TEST[setup:sales]
142+
// TEST[catch:bad_request]
125143

126-
==== Examples
144+
[source,js]
145+
--------------------------------------------------
146+
{
147+
"error" : {
148+
"root_cause" : [...],
149+
"type" : "x_content_parse_exception",
150+
"reason" : "[1:82] [date_histogram] failed to parse field [calendar_interval]",
151+
"caused_by" : {
152+
"type" : "illegal_argument_exception",
153+
"reason" : "The supplied interval [2d] could not be parsed as a calendar interval.",
154+
"stack_trace" : "java.lang.IllegalArgumentException: The supplied interval [2d] could not be parsed as a calendar interval."
155+
}
156+
}
157+
}
158+
159+
--------------------------------------------------
160+
// NOTCONSOLE
161+
162+
===== Fixed Intervals
163+
164+
Fixed intervals are configured with the `fixed_interval` parameter.
165+
166+
In contrast to calendar-aware intervals, fixed intervals are a fixed number of SI
167+
units and never deviate, regardless of where they fall on the calendar. One second
168+
is always composed of 1000ms. This allows fixed intervals to be specified in
169+
any multiple of the supported units.
170+
171+
However, it means fixed intervals cannot express other units such as months,
172+
since the duration of a month is not a fixed quantity. Attempting to specify
173+
a calendar interval like month or quarter will throw an exception.
174+
175+
The accepted units for fixed intervals are:
176+
177+
milliseconds (ms) ::
178+
179+
seconds (s) ::
180+
Defined as 1000 milliseconds each
181+
182+
minutes (m) ::
183+
All minutes begin at 00 seconds.
127184

128-
Requesting bucket intervals of a month.
185+
Defined as 60 seconds each (60,000 milliseconds)
186+
187+
hours (h) ::
188+
All hours begin at 00 minutes and 00 seconds.
189+
Defined as 60 minutes each (3,600,000 milliseconds)
190+
191+
days (d) ::
192+
All days begin at the earliest possible time, which is usually 00:00:00
193+
(midnight).
194+
195+
Defined as 24 hours (86,400,000 milliseconds)
196+
197+
===== Fixed Interval Examples
198+
199+
If we try to recreate the "month" `calendar_interval` from earlier, we can approximate that with
200+
30 fixed days:
129201

130202
[source,js]
131203
--------------------------------------------------
@@ -135,7 +207,7 @@ POST /sales/_search?size=0
135207
"sales_over_time" : {
136208
"date_histogram" : {
137209
"field" : "date",
138-
"calendar_interval" : "month"
210+
"fixed_interval" : "30d"
139211
}
140212
}
141213
}
@@ -144,11 +216,7 @@ POST /sales/_search?size=0
144216
// CONSOLE
145217
// TEST[setup:sales]
146218

147-
You can also specify time values using abbreviations supported by
148-
<<time-units,time units>> parsing.
149-
Note that fractional time values are not supported, but you can address this by
150-
shifting to another
151-
time unit (e.g., `1.5h` could instead be specified as `90m`).
219+
But if we try to use a calendar unit that is not supported, such as weeks, we'll get an exception:
152220

153221
[source,js]
154222
--------------------------------------------------
@@ -158,14 +226,58 @@ POST /sales/_search?size=0
158226
"sales_over_time" : {
159227
"date_histogram" : {
160228
"field" : "date",
161-
"fixed_interval" : "90m"
229+
"fixed_interval" : "2w"
162230
}
163231
}
164232
}
165233
}
166234
--------------------------------------------------
167235
// CONSOLE
168236
// TEST[setup:sales]
237+
// TEST[catch:bad_request]
238+
239+
[source,js]
240+
--------------------------------------------------
241+
{
242+
"error" : {
243+
"root_cause" : [...],
244+
"type" : "x_content_parse_exception",
245+
"reason" : "[1:82] [date_histogram] failed to parse field [fixed_interval]",
246+
"caused_by" : {
247+
"type" : "illegal_argument_exception",
248+
"reason" : "failed to parse setting [date_histogram.fixedInterval] with value [2w] as a time value: unit is missing or unrecognized",
249+
"stack_trace" : "java.lang.IllegalArgumentException: failed to parse setting [date_histogram.fixedInterval] with value [2w] as a time value: unit is missing or unrecognized"
250+
}
251+
}
252+
}
253+
254+
--------------------------------------------------
255+
// NOTCONSOLE
256+
257+
===== Notes
258+
259+
In all cases, when the specified end time does not exist, the actual end time is
260+
the closest available time after the specified end.
261+
262+
Widely distributed applications must also consider vagaries such as countries that
263+
start and stop daylight savings time at 12:01 A.M., so end up with one minute of
264+
Sunday followed by an additional 59 minutes of Saturday once a year, and countries
265+
that decide to move across the international date line. Situations like
266+
that can make irregular timezone offsets seem easy.
267+
268+
As always, rigorous testing, especially around time-change events, will ensure
269+
that your time interval specification is
270+
what you intend it to be.
271+
272+
WARNING:
273+
To avoid unexpected results, all connected servers and clients must sync to a
274+
reliable network time service.
275+
276+
NOTE: fractional time values are not supported, but you can address this by
277+
shifting to another time unit (e.g., `1.5h` could instead be specified as `90m`).
278+
279+
NOTE: You can also specify time values using abbreviations supported by
280+
<<time-units,time units>> parsing.
169281

170282
===== Keys
171283

@@ -522,8 +634,6 @@ control the order using
522634
the `order` setting. This setting supports the same `order` functionality as
523635
<<search-aggregations-bucket-terms-aggregation-order,`Terms Aggregation`>>.
524636

525-
deprecated[6.0.0, Use `_key` instead of `_time` to order buckets by their dates/keys]
526-
527637
===== Using a script to aggregate by day of the week
528638

529639
When you need to aggregate the results by day of the week, use a script that

0 commit comments

Comments
 (0)