@Override
 public void collect(int doc) throws IOException {
   if (values != null) {
     int ord = (int) ordinals.getOrd(doc);
     long parentIdx = parentIdsIndex.get(ord);
     if (parentIdx < 0) {
       final BytesRef bytes = values.getValueByOrd(ord);
       final int hash = values.currentValueHash();
       parentIdx = parentIds.add(bytes, hash);
       if (parentIdx < 0) {
         parentIdx = -parentIdx - 1;
         scores.increment(parentIdx, scorer.score());
         occurrences.increment(parentIdx, 1);
       } else {
         scores = bigArrays.grow(scores, parentIdx + 1);
         scores.set(parentIdx, scorer.score());
         occurrences = bigArrays.grow(occurrences, parentIdx + 1);
         occurrences.set(parentIdx, 1);
       }
       parentIdsIndex.set(ord, parentIdx);
     } else {
       scores.increment(parentIdx, scorer.score());
       occurrences.increment(parentIdx, 1);
     }
   }
 }
 /**
  * Utility method to return the number of documents that fell in the given bucket (identified by
  * the bucket ordinal)
  */
 public final int bucketDocCount(long bucketOrd) {
   if (bucketOrd >= docCounts.size()) {
     // This may happen eg. if no document in the highest buckets is accepted by a sub aggregator.
     // For example, if there is a long terms agg on 3 terms 1,2,3 with a sub filter aggregator and
     // if no document with 3 as a value
     // matches the filter, then the filter will never collect bucket ord 3. However, the long
     // terms agg will call bucketAggregations(3)
     // on the filter aggregator anyway to build sub-aggregations.
     return 0;
   } else {
     return docCounts.get(bucketOrd);
   }
 }
      @Override
      public int advance(int target) throws IOException {
        if (remaining == 0) {
          return currentDocId = NO_MORE_DOCS;
        }

        currentDocId = parentsIterator.advance(target);
        if (currentDocId == DocIdSetIterator.NO_MORE_DOCS) {
          return currentDocId;
        }

        bytesValues.setDocument(currentDocId);
        long index = parentIds.find(bytesValues.nextValue(), bytesValues.currentValueHash());
        if (index != -1) {
          currentScore = scores.get(index);
          currentScore /= occurrences.get(index);
          remaining--;
          return currentDocId;
        } else {
          return nextDoc();
        }
      }
 /**
  * Utility method to increment the doc counts of the given bucket (identified by the bucket
  * ordinal)
  */
 protected final void incrementBucketDocCount(long bucketOrd, int inc) throws IOException {
   docCounts = bigArrays.grow(docCounts, bucketOrd + 1);
   docCounts.increment(bucketOrd, inc);
 }
 /**
  * Same as {@link #collectBucket(int, long)}, but doesn't check if the docCounts needs to be
  * re-sized.
  */
 protected final void collectExistingBucket(int doc, long bucketOrd) throws IOException {
   docCounts.increment(bucketOrd, 1);
   collectBucketNoCounts(doc, bucketOrd);
 }
 /** Return an upper bound of the maximum bucket ordinal seen so far. */
 protected final long maxBucketOrd() {
   return docCounts.size();
 }