43
43
import java .util .ListIterator ;
44
44
import java .util .Map ;
45
45
import java .util .Objects ;
46
+ import java .util .stream .Collectors ;
46
47
47
48
/**
48
49
* Implementation of {@link Histogram}.
@@ -207,15 +208,17 @@ public int hashCode() {
207
208
private final DocValueFormat format ;
208
209
private final BucketInfo bucketInfo ;
209
210
private final int targetBuckets ;
211
+ private final long numValuesCollected ;
210
212
211
213
212
- InternalAutoDateHistogram (String name , List <Bucket > buckets , int targetBuckets , BucketInfo emptyBucketInfo , DocValueFormat formatter ,
213
- List <PipelineAggregator > pipelineAggregators , Map <String , Object > metaData ) {
214
+ InternalAutoDateHistogram (String name , List <Bucket > buckets , int targetBuckets , long numValuesCollected , BucketInfo emptyBucketInfo ,
215
+ DocValueFormat formatter , List <PipelineAggregator > pipelineAggregators , Map <String , Object > metaData ) {
214
216
super (name , pipelineAggregators , metaData );
215
217
this .buckets = buckets ;
216
218
this .bucketInfo = emptyBucketInfo ;
217
219
this .format = formatter ;
218
220
this .targetBuckets = targetBuckets ;
221
+ this .numValuesCollected = numValuesCollected ;
219
222
}
220
223
221
224
/**
@@ -227,6 +230,7 @@ public InternalAutoDateHistogram(StreamInput in) throws IOException {
227
230
format = in .readNamedWriteable (DocValueFormat .class );
228
231
buckets = in .readList (stream -> new Bucket (stream , format ));
229
232
this .targetBuckets = in .readVInt ();
233
+ this .numValuesCollected = in .readVLong ();
230
234
}
231
235
232
236
@ Override
@@ -235,6 +239,7 @@ protected void doWriteTo(StreamOutput out) throws IOException {
235
239
out .writeNamedWriteable (format );
236
240
out .writeList (buckets );
237
241
out .writeVInt (targetBuckets );
242
+ out .writeVLong (numValuesCollected );
238
243
}
239
244
240
245
@ Override
@@ -255,13 +260,18 @@ public int getTargetBuckets() {
255
260
return targetBuckets ;
256
261
}
257
262
263
+ public long getNumValuesCollected () {
264
+ return numValuesCollected ;
265
+ }
266
+
258
267
public BucketInfo getBucketInfo () {
259
268
return bucketInfo ;
260
269
}
261
270
262
271
@ Override
263
272
public InternalAutoDateHistogram create (List <Bucket > buckets ) {
264
- return new InternalAutoDateHistogram (name , buckets , targetBuckets , bucketInfo , format , pipelineAggregators (), metaData );
273
+ return new InternalAutoDateHistogram (name , buckets , targetBuckets , numValuesCollected , bucketInfo , format , pipelineAggregators (),
274
+ metaData );
265
275
}
266
276
267
277
@ Override
@@ -365,7 +375,8 @@ private BucketReduceResult mergeBucketsIfNeeded(List<Bucket> reducedBuckets, int
365
375
return new BucketReduceResult (reducedBuckets , reduceRounding , reduceRoundingIdx );
366
376
}
367
377
368
- private List <Bucket > mergeBuckets (List <Bucket > reducedBuckets , Rounding reduceRounding , ReduceContext reduceContext ) {
378
+ private List <Bucket > mergeBuckets (List <Bucket > reducedBuckets , Rounding reduceRounding ,
379
+ ReduceContext reduceContext ) {
369
380
List <Bucket > mergedBuckets = new ArrayList <>();
370
381
371
382
List <Bucket > sameKeyedBuckets = new ArrayList <>();
@@ -409,12 +420,13 @@ private static class BucketReduceResult {
409
420
}
410
421
}
411
422
412
- private BucketReduceResult addEmptyBuckets (BucketReduceResult currentResult , ReduceContext reduceContext ) {
423
+ private BucketReduceResult addEmptyBuckets (BucketReduceResult currentResult , long numValuesCollected , ReduceContext reduceContext ) {
413
424
List <Bucket > list = currentResult .buckets ;
414
425
if (list .isEmpty ()) {
415
426
return currentResult ;
416
427
}
417
- int roundingIdx = getAppropriateRounding (list .get (0 ).key , list .get (list .size () - 1 ).key , currentResult .roundingIdx ,
428
+ double maxBuckets = Math .max (targetBuckets , targetBuckets * Math .log (numValuesCollected ));
429
+ int roundingIdx = getAppropriateRounding (list .get (0 ).key , list .get (list .size () - 1 ).key , maxBuckets , currentResult .roundingIdx ,
418
430
bucketInfo .roundings );
419
431
Rounding rounding = bucketInfo .roundings [roundingIdx ];
420
432
// merge buckets using the new rounding
@@ -443,7 +455,7 @@ private BucketReduceResult addEmptyBuckets(BucketReduceResult currentResult, Red
443
455
return new BucketReduceResult (list , rounding , roundingIdx );
444
456
}
445
457
446
- private int getAppropriateRounding (long minKey , long maxKey , int roundingIdx , Rounding [] roundings ) {
458
+ private int getAppropriateRounding (long minKey , long maxKey , double maxBuckets , int roundingIdx , Rounding [] roundings ) {
447
459
if (roundingIdx == roundings .length - 1 ) {
448
460
return roundingIdx ;
449
461
}
@@ -458,18 +470,21 @@ private int getAppropriateRounding(long minKey, long maxKey, int roundingIdx, Ro
458
470
currentKey = currentRounding .nextRoundingValue (currentKey );
459
471
}
460
472
currentRoundingIdx ++;
461
- } while (requiredBuckets > targetBuckets && currentRoundingIdx < roundings .length );
473
+ } while (requiredBuckets > maxBuckets && currentRoundingIdx < roundings .length );
462
474
// The loop will increase past the correct rounding index here so we
463
475
// need to subtract one to get the rounding index we need
464
476
return currentRoundingIdx - 1 ;
465
477
}
466
478
467
479
@ Override
468
480
public InternalAggregation doReduce (List <InternalAggregation > aggregations , ReduceContext reduceContext ) {
481
+ long numValuesCollected = aggregations .stream ()
482
+ .collect (Collectors .summingLong (agg -> ((InternalAutoDateHistogram ) agg ).getNumValuesCollected ()));
483
+
469
484
BucketReduceResult reducedBucketsResult = reduceBuckets (aggregations , reduceContext );
470
485
471
486
// adding empty buckets if needed
472
- reducedBucketsResult = addEmptyBuckets (reducedBucketsResult , reduceContext );
487
+ reducedBucketsResult = addEmptyBuckets (reducedBucketsResult , numValuesCollected , reduceContext );
473
488
474
489
// Adding empty buckets may have tipped us over the target so merge the buckets again if needed
475
490
reducedBucketsResult = mergeBucketsIfNeeded (reducedBucketsResult .buckets , reducedBucketsResult .roundingIdx ,
@@ -478,7 +493,7 @@ public InternalAggregation doReduce(List<InternalAggregation> aggregations, Redu
478
493
BucketInfo bucketInfo = new BucketInfo (this .bucketInfo .roundings , reducedBucketsResult .roundingIdx ,
479
494
this .bucketInfo .emptySubAggregations );
480
495
481
- return new InternalAutoDateHistogram (getName (), reducedBucketsResult .buckets , targetBuckets , bucketInfo , format ,
496
+ return new InternalAutoDateHistogram (getName (), reducedBucketsResult .buckets , targetBuckets , numValuesCollected , bucketInfo , format ,
482
497
pipelineAggregators (), getMetaData ());
483
498
}
484
499
@@ -512,7 +527,8 @@ public InternalAggregation createAggregation(List<MultiBucketsAggregation.Bucket
512
527
buckets2 .add ((Bucket ) b );
513
528
}
514
529
buckets2 = Collections .unmodifiableList (buckets2 );
515
- return new InternalAutoDateHistogram (name , buckets2 , targetBuckets , bucketInfo , format , pipelineAggregators (), getMetaData ());
530
+ return new InternalAutoDateHistogram (name , buckets2 , targetBuckets , numValuesCollected , bucketInfo , format , pipelineAggregators (),
531
+ getMetaData ());
516
532
}
517
533
518
534
@ Override
@@ -524,6 +540,8 @@ public Bucket createBucket(Number key, long docCount, InternalAggregations aggre
524
540
protected boolean doEquals (Object obj ) {
525
541
InternalAutoDateHistogram that = (InternalAutoDateHistogram ) obj ;
526
542
return Objects .equals (buckets , that .buckets )
543
+ && Objects .equals (targetBuckets , that .targetBuckets )
544
+ && Objects .equals (numValuesCollected , that .numValuesCollected )
527
545
&& Objects .equals (format , that .format )
528
546
&& Objects .equals (bucketInfo , that .bucketInfo );
529
547
}
0 commit comments