4040
4141import java .io .IOException ;
4242import java .util .ArrayList ;
43- import java .util .Collection ;
4443import java .util .HashMap ;
4544import java .util .List ;
4645import java .util .Map ;
@@ -329,7 +328,11 @@ protected LeafBucketCollector getLeafCollector(AggregationExecutionContext aggCt
329328 hasOtherBucket
330329 );
331330 }
332- return new MultiFilterLeafCollector (sub , filterWrappers , numFilters , totalNumKeys , usesCompetitiveIterator , hasOtherBucket );
331+ if (usesCompetitiveIterator ) {
332+ return new MultiFilterCompetitiveLeafCollector (sub , filterWrappers , numFilters , totalNumKeys , hasOtherBucket );
333+ } else {
334+ return new MultiFilterLeafCollector (sub , filterWrappers , numFilters , totalNumKeys , hasOtherBucket );
335+ }
333336 }
334337 }
335338
@@ -401,20 +404,19 @@ public DocIdSetIterator competitiveIterator() throws IOException {
401404 }
402405 }
403406
404- private class MultiFilterLeafCollector extends AbstractLeafCollector {
407+ private final class MultiFilterLeafCollector extends AbstractLeafCollector {
405408
406409 // A DocIdSetIterator heap with one entry for each filter, ordered by doc ID
407- final DisiPriorityQueue filterIterators ;
410+ DisiPriorityQueue filterIterators ;
408411
409412 MultiFilterLeafCollector (
410413 LeafBucketCollector sub ,
411414 List <FilterMatchingDisiWrapper > filterWrappers ,
412415 int numFilters ,
413416 int totalNumKeys ,
414- boolean usesCompetitiveIterator ,
415417 boolean hasOtherBucket
416418 ) {
417- super (sub , numFilters , totalNumKeys , usesCompetitiveIterator , hasOtherBucket );
419+ super (sub , numFilters , totalNumKeys , false , hasOtherBucket );
418420 filterIterators = filterWrappers .isEmpty () ? null : new DisiPriorityQueue (filterWrappers .size ());
419421 for (FilterMatchingDisiWrapper wrapper : filterWrappers ) {
420422 filterIterators .add (wrapper );
@@ -424,7 +426,7 @@ private class MultiFilterLeafCollector extends AbstractLeafCollector {
424426 public void collect (int doc , long bucket ) throws IOException {
425427 boolean matched = false ;
426428 if (filterIterators != null ) {
427- // Advance filters if necessary. Filters will already be advanced if used as a competitive iterator.
429+ // Advance filters if necessary.
428430 DisiWrapper top = filterIterators .top ();
429431 while (top .doc < doc ) {
430432 top .doc = top .approximation .advance (doc );
@@ -449,18 +451,51 @@ public void collect(int doc, long bucket) throws IOException {
449451 }
450452
451453 @ Override
452- public DocIdSetIterator competitiveIterator () throws IOException {
453- if (usesCompetitiveIterator ) {
454- // A DocIdSetIterator view of the filterIterators heap
455- assert filterIterators != null ;
456- Collection <DisiWrapper > actualList = new ArrayList <>();
457- filterIterators .iterator ().forEachRemaining (actualList ::add );
458- return DisjunctionDISIApproximation .of (actualList , Long .MAX_VALUE );
459- }
454+ public DocIdSetIterator competitiveIterator () {
460455 return null ;
461456 }
462457 }
463458
459+ private final class MultiFilterCompetitiveLeafCollector extends AbstractLeafCollector {
460+
461+ private final DisjunctionDISIApproximation disjunctionDisi ;
462+
463+ MultiFilterCompetitiveLeafCollector (
464+ LeafBucketCollector sub ,
465+ List <FilterMatchingDisiWrapper > filterWrappers ,
466+ int numFilters ,
467+ int totalNumKeys ,
468+ boolean hasOtherBucket
469+ ) {
470+ super (sub , numFilters , totalNumKeys , true , hasOtherBucket );
471+ assert filterWrappers .isEmpty () == false ;
472+ disjunctionDisi = DisjunctionDISIApproximation .of (List .copyOf (filterWrappers ), Long .MAX_VALUE );
473+ }
474+
475+ public void collect (int doc , long bucket ) throws IOException {
476+ boolean matched = false ;
477+ var top = disjunctionDisi .topList ();
478+ if (top .doc == doc ) {
479+ for (DisiWrapper w = disjunctionDisi .topList (); w != null ; w = w .next ) {
480+ FilterMatchingDisiWrapper topMatch = (FilterMatchingDisiWrapper ) w ;
481+ if (topMatch .checkDocForMatch (doc )) {
482+ collectBucket (sub , doc , bucketOrd (bucket , topMatch .filterOrd ));
483+ matched = true ;
484+ }
485+ }
486+ }
487+
488+ if (hasOtherBucket && false == matched ) {
489+ collectBucket (sub , doc , bucketOrd (bucket , numFilters ));
490+ }
491+ }
492+
493+ @ Override
494+ public DocIdSetIterator competitiveIterator () {
495+ return disjunctionDisi ;
496+ }
497+ }
498+
464499 private static class FilterMatchingDisiWrapper extends DisiWrapper {
465500 final int filterOrd ;
466501
0 commit comments