@@ -206,6 +206,7 @@ pub struct SegmentHistogramCollector {
206
206
field_type : Type ,
207
207
interval : f64 ,
208
208
offset : f64 ,
209
+ min_doc_count : u64 ,
209
210
first_bucket_num : i64 ,
210
211
bounds : HistogramBounds ,
211
212
}
@@ -215,6 +216,30 @@ impl SegmentHistogramCollector {
215
216
self ,
216
217
agg_with_accessor : & BucketAggregationWithAccessor ,
217
218
) -> crate :: Result < IntermediateBucketResult > {
219
+ // Compute the number of buckets to validate against max num buckets
220
+ // Note: We use min_doc_count here, but it's only an lowerbound here, since were are on the
221
+ // intermediate level and after merging the number of documents of a bucket could exceed
222
+ // `min_doc_count`.
223
+ {
224
+ let cut_off_buckets_front = self
225
+ . buckets
226
+ . iter ( )
227
+ . take_while ( |bucket| bucket. doc_count <= self . min_doc_count )
228
+ . count ( ) ;
229
+ let cut_off_buckets_back = self . buckets [ cut_off_buckets_front..]
230
+ . iter ( )
231
+ . rev ( )
232
+ . take_while ( |bucket| bucket. doc_count <= self . min_doc_count )
233
+ . count ( ) ;
234
+ let estimate_num_buckets =
235
+ self . buckets . len ( ) - cut_off_buckets_front - cut_off_buckets_back;
236
+
237
+ agg_with_accessor
238
+ . bucket_count
239
+ . add_count ( estimate_num_buckets as u32 ) ;
240
+ agg_with_accessor. bucket_count . validate_bucket_count ( ) ?;
241
+ }
242
+
218
243
let mut buckets = Vec :: with_capacity (
219
244
self . buckets
220
245
. iter ( )
@@ -251,11 +276,6 @@ impl SegmentHistogramCollector {
251
276
) ;
252
277
} ;
253
278
254
- agg_with_accessor
255
- . bucket_count
256
- . add_count ( buckets. len ( ) as u32 ) ;
257
- agg_with_accessor. bucket_count . validate_bucket_count ( ) ?;
258
-
259
279
Ok ( IntermediateBucketResult :: Histogram { buckets } )
260
280
}
261
281
@@ -308,6 +328,7 @@ impl SegmentHistogramCollector {
308
328
first_bucket_num,
309
329
bounds,
310
330
sub_aggregations,
331
+ min_doc_count : req. min_doc_count ( ) ,
311
332
} )
312
333
}
313
334
@@ -1521,4 +1542,36 @@ mod tests {
1521
1542
1522
1543
Ok ( ( ) )
1523
1544
}
1545
+
1546
+ #[ test]
1547
+ fn histogram_test_max_buckets_segments ( ) -> crate :: Result < ( ) > {
1548
+ let values = vec ! [ 0.0 , 70000.0 ] ;
1549
+
1550
+ let index = get_test_index_from_values ( true , & values) ?;
1551
+
1552
+ let agg_req: Aggregations = vec ! [ (
1553
+ "my_interval" . to_string( ) ,
1554
+ Aggregation :: Bucket ( BucketAggregation {
1555
+ bucket_agg: BucketAggregationType :: Histogram ( HistogramAggregation {
1556
+ field: "score_f64" . to_string( ) ,
1557
+ interval: 1.0 ,
1558
+ ..Default :: default ( )
1559
+ } ) ,
1560
+ sub_aggregation: Default :: default ( ) ,
1561
+ } ) ,
1562
+ ) ]
1563
+ . into_iter ( )
1564
+ . collect ( ) ;
1565
+
1566
+ let res = exec_request ( agg_req, & index) ;
1567
+
1568
+ assert_eq ! (
1569
+ res. unwrap_err( ) . to_string( ) ,
1570
+ "An invalid argument was passed: 'Aborting aggregation because too many buckets were \
1571
+ created'"
1572
+ . to_string( )
1573
+ ) ;
1574
+
1575
+ Ok ( ( ) )
1576
+ }
1524
1577
}
0 commit comments