@@ -67,6 +67,13 @@ pub struct DateHistogramAggregationReq {
67
67
pub fixed_interval : Option < String > ,
68
68
/// Intervals implicitly defines an absolute grid of buckets `[interval * k, interval * (k +
69
69
/// 1))`.
70
+ ///
71
+ /// Offset makes it possible to shift this grid into
72
+ /// `[offset + interval * k, offset + interval * (k + 1))`. Offset has to be in the range [0,
73
+ /// interval).
74
+ ///
75
+ /// The `offset` parameter is has the same syntax as the `fixed_interval` parameter, but
76
+ /// also allows for negative values.
70
77
pub offset : Option < String > ,
71
78
/// The minimum number of documents in a bucket to be returned. Defaults to 0.
72
79
pub min_doc_count : Option < u64 > ,
@@ -77,7 +84,7 @@ pub struct DateHistogramAggregationReq {
77
84
/// hard_bounds only limits the buckets, to force a range set both extended_bounds and
78
85
/// hard_bounds to the same range.
79
86
///
80
- /// Needs to be provided as timestamp in nanosecond precision.
87
+ /// Needs to be provided as timestamp in millisecond precision.
81
88
///
82
89
/// ## Example
83
90
/// ```json
@@ -88,7 +95,7 @@ pub struct DateHistogramAggregationReq {
88
95
/// "interval": "1d",
89
96
/// "hard_bounds": {
90
97
/// "min": 0,
91
- /// "max": 1420502400000000000
98
+ /// "max": 1420502400000
92
99
/// }
93
100
/// }
94
101
/// }
@@ -114,11 +121,11 @@ impl DateHistogramAggregationReq {
114
121
self . validate ( ) ?;
115
122
Ok ( HistogramAggregation {
116
123
field : self . field . to_string ( ) ,
117
- interval : parse_into_nanoseconds ( self . fixed_interval . as_ref ( ) . unwrap ( ) ) ? as f64 ,
124
+ interval : parse_into_milliseconds ( self . fixed_interval . as_ref ( ) . unwrap ( ) ) ? as f64 ,
118
125
offset : self
119
126
. offset
120
127
. as_ref ( )
121
- . map ( |offset| parse_offset_into_nanosecs ( offset) )
128
+ . map ( |offset| parse_offset_into_milliseconds ( offset) )
122
129
. transpose ( ) ?
123
130
. map ( |el| el as f64 ) ,
124
131
min_doc_count : self . min_doc_count ,
@@ -153,7 +160,7 @@ impl DateHistogramAggregationReq {
153
160
) ) ;
154
161
}
155
162
156
- parse_into_nanoseconds ( self . fixed_interval . as_ref ( ) . unwrap ( ) ) ?;
163
+ parse_into_milliseconds ( self . fixed_interval . as_ref ( ) . unwrap ( ) ) ?;
157
164
158
165
Ok ( ( ) )
159
166
}
@@ -179,7 +186,7 @@ pub enum DateHistogramParseError {
179
186
OutOfBounds ( String ) ,
180
187
}
181
188
182
- fn parse_offset_into_nanosecs ( input : & str ) -> Result < i64 , AggregationError > {
189
+ fn parse_offset_into_milliseconds ( input : & str ) -> Result < i64 , AggregationError > {
183
190
let is_sign = |byte| & [ byte] == b"-" || & [ byte] == b"+" ;
184
191
if input. is_empty ( ) {
185
192
return Err ( DateHistogramParseError :: InvalidOffset ( input. to_string ( ) ) . into ( ) ) ;
@@ -188,18 +195,18 @@ fn parse_offset_into_nanosecs(input: &str) -> Result<i64, AggregationError> {
188
195
let has_sign = is_sign ( input. as_bytes ( ) [ 0 ] ) ;
189
196
if has_sign {
190
197
let ( sign, input) = input. split_at ( 1 ) ;
191
- let val = parse_into_nanoseconds ( input) ?;
198
+ let val = parse_into_milliseconds ( input) ?;
192
199
if sign == "-" {
193
200
Ok ( -val)
194
201
} else {
195
202
Ok ( val)
196
203
}
197
204
} else {
198
- parse_into_nanoseconds ( input)
205
+ parse_into_milliseconds ( input)
199
206
}
200
207
}
201
208
202
- fn parse_into_nanoseconds ( input : & str ) -> Result < i64 , AggregationError > {
209
+ fn parse_into_milliseconds ( input : & str ) -> Result < i64 , AggregationError > {
203
210
let split_boundary = input
204
211
. as_bytes ( )
205
212
. iter ( )
@@ -218,17 +225,18 @@ fn parse_into_nanoseconds(input: &str) -> Result<i64, AggregationError> {
218
225
// here and being defensive does not hurt.
219
226
. map_err ( |_err| DateHistogramParseError :: NumberMissing ( input. to_string ( ) ) ) ?;
220
227
221
- let multiplier_from_unit = match unit {
222
- "ms" => 1 ,
223
- "s" => 1000 ,
224
- "m" => 60 * 1000 ,
225
- "h" => 60 * 60 * 1000 ,
226
- "d" => 24 * 60 * 60 * 1000 ,
228
+ let unit_in_ms = match unit {
229
+ "ms" | "milliseconds" => 1 ,
230
+ "s" | "seconds" => 1000 ,
231
+ "m" | "minutes" => 60 * 1000 ,
232
+ "h" | "hours" => 60 * 60 * 1000 ,
233
+ "d" | "days" => 24 * 60 * 60 * 1000 ,
227
234
_ => return Err ( DateHistogramParseError :: UnitNotRecognized ( unit. to_string ( ) ) . into ( ) ) ,
228
235
} ;
229
236
230
- let val = ( number * multiplier_from_unit)
231
- . checked_mul ( 1_000_000 )
237
+ let val = number * unit_in_ms;
238
+ // The field type is in nanoseconds precision, so validate the value to fit the range
239
+ val. checked_mul ( 1_000_000 )
232
240
. ok_or_else ( || DateHistogramParseError :: OutOfBounds ( input. to_string ( ) ) ) ?;
233
241
234
242
Ok ( val)
@@ -246,49 +254,50 @@ mod tests {
246
254
use crate :: Index ;
247
255
248
256
#[ test]
249
- fn test_parse_into_nanosecs ( ) {
250
- assert_eq ! ( parse_into_nanoseconds( "1m" ) . unwrap( ) , 60_000_000_000 ) ;
251
- assert_eq ! ( parse_into_nanoseconds( "2m" ) . unwrap( ) , 120_000_000_000 ) ;
257
+ fn test_parse_into_millisecs ( ) {
258
+ assert_eq ! ( parse_into_milliseconds( "1m" ) . unwrap( ) , 60_000 ) ;
259
+ assert_eq ! ( parse_into_milliseconds( "2m" ) . unwrap( ) , 120_000 ) ;
260
+ assert_eq ! ( parse_into_milliseconds( "2minutes" ) . unwrap( ) , 120_000 ) ;
252
261
assert_eq ! (
253
- parse_into_nanoseconds ( "2y" ) . unwrap_err( ) ,
262
+ parse_into_milliseconds ( "2y" ) . unwrap_err( ) ,
254
263
DateHistogramParseError :: UnitNotRecognized ( "y" . to_string( ) ) . into( )
255
264
) ;
256
265
assert_eq ! (
257
- parse_into_nanoseconds ( "2000" ) . unwrap_err( ) ,
266
+ parse_into_milliseconds ( "2000" ) . unwrap_err( ) ,
258
267
DateHistogramParseError :: UnitMissing ( "2000" . to_string( ) ) . into( )
259
268
) ;
260
269
assert_eq ! (
261
- parse_into_nanoseconds ( "ms" ) . unwrap_err( ) ,
270
+ parse_into_milliseconds ( "ms" ) . unwrap_err( ) ,
262
271
DateHistogramParseError :: NumberMissing ( "ms" . to_string( ) ) . into( )
263
272
) ;
264
273
}
265
274
266
275
#[ test]
267
- fn test_parse_offset_into_nanosecs ( ) {
268
- assert_eq ! ( parse_offset_into_nanosecs ( "1m" ) . unwrap( ) , 60_000_000_000 ) ;
269
- assert_eq ! ( parse_offset_into_nanosecs ( "+1m" ) . unwrap( ) , 60_000_000_000 ) ;
270
- assert_eq ! ( parse_offset_into_nanosecs ( "-1m" ) . unwrap( ) , -60_000_000_000 ) ;
271
- assert_eq ! ( parse_offset_into_nanosecs ( "2m" ) . unwrap( ) , 120_000_000_000 ) ;
272
- assert_eq ! ( parse_offset_into_nanosecs ( "+2m" ) . unwrap( ) , 120_000_000_000 ) ;
273
- assert_eq ! ( parse_offset_into_nanosecs ( "-2m" ) . unwrap( ) , -120_000_000_000 ) ;
274
- assert_eq ! ( parse_offset_into_nanosecs ( "-2ms" ) . unwrap( ) , -2_000_000 ) ;
276
+ fn test_parse_offset_into_milliseconds ( ) {
277
+ assert_eq ! ( parse_offset_into_milliseconds ( "1m" ) . unwrap( ) , 60_000 ) ;
278
+ assert_eq ! ( parse_offset_into_milliseconds ( "+1m" ) . unwrap( ) , 60_000 ) ;
279
+ assert_eq ! ( parse_offset_into_milliseconds ( "-1m" ) . unwrap( ) , -60_000 ) ;
280
+ assert_eq ! ( parse_offset_into_milliseconds ( "2m" ) . unwrap( ) , 120_000 ) ;
281
+ assert_eq ! ( parse_offset_into_milliseconds ( "+2m" ) . unwrap( ) , 120_000 ) ;
282
+ assert_eq ! ( parse_offset_into_milliseconds ( "-2m" ) . unwrap( ) , -120_000 ) ;
283
+ assert_eq ! ( parse_offset_into_milliseconds ( "-2ms" ) . unwrap( ) , -2 ) ;
275
284
assert_eq ! (
276
- parse_offset_into_nanosecs ( "2y" ) . unwrap_err( ) ,
285
+ parse_offset_into_milliseconds ( "2y" ) . unwrap_err( ) ,
277
286
DateHistogramParseError :: UnitNotRecognized ( "y" . to_string( ) ) . into( )
278
287
) ;
279
288
assert_eq ! (
280
- parse_offset_into_nanosecs ( "2000" ) . unwrap_err( ) ,
289
+ parse_offset_into_milliseconds ( "2000" ) . unwrap_err( ) ,
281
290
DateHistogramParseError :: UnitMissing ( "2000" . to_string( ) ) . into( )
282
291
) ;
283
292
assert_eq ! (
284
- parse_offset_into_nanosecs ( "ms" ) . unwrap_err( ) ,
293
+ parse_offset_into_milliseconds ( "ms" ) . unwrap_err( ) ,
285
294
DateHistogramParseError :: NumberMissing ( "ms" . to_string( ) ) . into( )
286
295
) ;
287
296
}
288
297
289
298
#[ test]
290
299
fn test_parse_into_milliseconds_do_not_accept_non_ascii ( ) {
291
- assert ! ( parse_into_nanoseconds ( "1m" ) . is_err( ) ) ;
300
+ assert ! ( parse_into_milliseconds ( "1m" ) . is_err( ) ) ;
292
301
}
293
302
294
303
pub fn get_test_index_from_docs (
@@ -369,7 +378,7 @@ mod tests {
369
378
"buckets" : [
370
379
{
371
380
"key_as_string" : "2015-01-01T00:00:00Z" ,
372
- "key" : 1420070400000000000 .0,
381
+ "key" : 1420070400000 .0,
373
382
"doc_count" : 4
374
383
}
375
384
]
@@ -407,7 +416,7 @@ mod tests {
407
416
"buckets" : [
408
417
{
409
418
"key_as_string" : "2015-01-01T00:00:00Z" ,
410
- "key" : 1420070400000000000 .0,
419
+ "key" : 1420070400000 .0,
411
420
"doc_count" : 4 ,
412
421
"texts" : {
413
422
"buckets" : [
@@ -456,32 +465,32 @@ mod tests {
456
465
"buckets" : [
457
466
{
458
467
"doc_count" : 2 ,
459
- "key" : 1420070400000000000 .0,
468
+ "key" : 1420070400000 .0,
460
469
"key_as_string" : "2015-01-01T00:00:00Z"
461
470
} ,
462
471
{
463
472
"doc_count" : 1 ,
464
- "key" : 1420156800000000000 .0,
473
+ "key" : 1420156800000 .0,
465
474
"key_as_string" : "2015-01-02T00:00:00Z"
466
475
} ,
467
476
{
468
477
"doc_count" : 0 ,
469
- "key" : 1420243200000000000 .0,
478
+ "key" : 1420243200000 .0,
470
479
"key_as_string" : "2015-01-03T00:00:00Z"
471
480
} ,
472
481
{
473
482
"doc_count" : 0 ,
474
- "key" : 1420329600000000000 .0,
483
+ "key" : 1420329600000 .0,
475
484
"key_as_string" : "2015-01-04T00:00:00Z"
476
485
} ,
477
486
{
478
487
"doc_count" : 0 ,
479
- "key" : 1420416000000000000 .0,
488
+ "key" : 1420416000000 .0,
480
489
"key_as_string" : "2015-01-05T00:00:00Z"
481
490
} ,
482
491
{
483
492
"doc_count" : 1 ,
484
- "key" : 1420502400000000000 .0,
493
+ "key" : 1420502400000 .0,
485
494
"key_as_string" : "2015-01-06T00:00:00Z"
486
495
}
487
496
]
@@ -499,8 +508,8 @@ mod tests {
499
508
"field" : "date" ,
500
509
"fixed_interval" : "1d" ,
501
510
"extended_bounds" : {
502
- "min" : 1419984000000000000 .0,
503
- "max" : 1420588800000000000 .0
511
+ "min" : 1419984000000 .0,
512
+ "max" : 1420588800000 .0
504
513
}
505
514
}
506
515
}
@@ -517,42 +526,42 @@ mod tests {
517
526
"buckets" : [
518
527
{
519
528
"doc_count" : 0 ,
520
- "key" : 1419984000000000000 .0,
529
+ "key" : 1419984000000 .0,
521
530
"key_as_string" : "2014-12-31T00:00:00Z"
522
531
} ,
523
532
{
524
533
"doc_count" : 2 ,
525
- "key" : 1420070400000000000 .0,
534
+ "key" : 1420070400000 .0,
526
535
"key_as_string" : "2015-01-01T00:00:00Z"
527
536
} ,
528
537
{
529
538
"doc_count" : 1 ,
530
- "key" : 1420156800000000000 .0,
539
+ "key" : 1420156800000 .0,
531
540
"key_as_string" : "2015-01-02T00:00:00Z"
532
541
} ,
533
542
{
534
543
"doc_count" : 0 ,
535
- "key" : 1420243200000000000 .0,
544
+ "key" : 1420243200000 .0,
536
545
"key_as_string" : "2015-01-03T00:00:00Z"
537
546
} ,
538
547
{
539
548
"doc_count" : 0 ,
540
- "key" : 1420329600000000000 .0,
549
+ "key" : 1420329600000 .0,
541
550
"key_as_string" : "2015-01-04T00:00:00Z"
542
551
} ,
543
552
{
544
553
"doc_count" : 0 ,
545
- "key" : 1420416000000000000 .0,
554
+ "key" : 1420416000000 .0,
546
555
"key_as_string" : "2015-01-05T00:00:00Z"
547
556
} ,
548
557
{
549
558
"doc_count" : 1 ,
550
- "key" : 1420502400000000000 .0,
559
+ "key" : 1420502400000 .0,
551
560
"key_as_string" : "2015-01-06T00:00:00Z"
552
561
} ,
553
562
{
554
563
"doc_count" : 0 ,
555
- "key" : 1.4205888e18 ,
564
+ "key" : 1420588800000.0 ,
556
565
"key_as_string" : "2015-01-07T00:00:00Z"
557
566
}
558
567
]
@@ -569,8 +578,8 @@ mod tests {
569
578
"field" : "date" ,
570
579
"fixed_interval" : "1d" ,
571
580
"hard_bounds" : {
572
- "min" : 1420156800000000000 .0,
573
- "max" : 1420243200000000000 .0
581
+ "min" : 1420156800000 .0,
582
+ "max" : 1420243200000 .0
574
583
}
575
584
}
576
585
}
@@ -587,7 +596,7 @@ mod tests {
587
596
"buckets" : [
588
597
{
589
598
"doc_count" : 1 ,
590
- "key" : 1420156800000000000 .0,
599
+ "key" : 1420156800000 .0,
591
600
"key_as_string" : "2015-01-02T00:00:00Z"
592
601
}
593
602
]
0 commit comments