Class OverlappingLongRangeCounter

java.lang.Object
org.apache.lucene.facet.range.LongRangeCounter
org.apache.lucene.facet.range.OverlappingLongRangeCounter

class OverlappingLongRangeCounter extends LongRangeCounter
This implementation supports requested ranges that overlap. Because of this, we use a segment-tree to more efficiently aggregate counts into ranges at the end of processing. We also need to worry about double-counting issues since it's possible that multiple elementary intervals, although mutually-exclusive, can roll-up to the same requested range. This creates some complexity with how we need to handle multi-valued documents.
  • Field Details

    • root

      segment tree root node
    • boundaries

      private final long[] boundaries
      elementary interval boundaries used for efficient counting (bsearch to find interval)
    • hasUnflushedCounts

      private boolean hasUnflushedCounts
      whether-or-not there are elementary interval counts that still need to be rolled up at the end
    • singleValuedElementaryIntervalCounts

      private int[] singleValuedElementaryIntervalCounts
      counts seen in each elementary interval
    • multiValuedDocElementaryIntervalHits

      private FixedBitSet multiValuedDocElementaryIntervalHits
      whether-or-not an elementary interval has seen at least one match for a single doc
    • multiValuedDocRangeHits

      private FixedBitSet multiValuedDocRangeHits
      whether-or-not a requested range has seen at least one match for a single doc
    • elementaryIntervalUpto

      private int elementaryIntervalUpto
    • missingCount

      private int missingCount
      number of counted documents that haven't matched any requested ranges
  • Constructor Details

    • OverlappingLongRangeCounter

      OverlappingLongRangeCounter(LongRange[] ranges, int[] countBuffer)
  • Method Details

    • startMultiValuedDoc

      void startMultiValuedDoc()
      Description copied from class: LongRangeCounter
      Start processing a new doc. It's unnecessary to call this for single-value cases.
      Overrides:
      startMultiValuedDoc in class LongRangeCounter
    • endMultiValuedDoc

      boolean endMultiValuedDoc()
      Description copied from class: LongRangeCounter
      Finish processing a new doc. Returns whether-or-not the document contributed a count to at least one range. It's unnecessary to call this for single-value cases.
      Specified by:
      endMultiValuedDoc in class LongRangeCounter
    • finish

      int finish()
      Description copied from class: LongRangeCounter
      Finish processing all documents. This will return the number of docs that didn't contribute to any ranges (that weren't already reported when calling endMultiValuedDoc()).
      Specified by:
      finish in class LongRangeCounter
    • boundaries

      protected long[] boundaries()
      Description copied from class: LongRangeCounter
      Provide boundary information for elementary intervals (max inclusive value per interval)
      Specified by:
      boundaries in class LongRangeCounter
    • processSingleValuedHit

      protected void processSingleValuedHit(int elementaryIntervalNum)
      Description copied from class: LongRangeCounter
      Process a single-value "hit" against an elementary interval.
      Specified by:
      processSingleValuedHit in class LongRangeCounter
    • processMultiValuedHit

      protected void processMultiValuedHit(int elementaryIntervalNum)
      Description copied from class: LongRangeCounter
      Process a multi-value "hit" against an elementary interval.
      Specified by:
      processMultiValuedHit in class LongRangeCounter
    • split

      private static OverlappingLongRangeCounter.LongRangeNode split(int start, int end, List<LongRangeCounter.InclusiveRange> elementaryIntervals)
    • rollupSingleValued

      private int rollupSingleValued(OverlappingLongRangeCounter.LongRangeNode node, boolean sawOutputs)
      Rolls up all the single-valued doc counts. Note that this is done once at the end of processing all documents (as part of finish(). This is done in bulk at the end for efficiency purposes (vs. after ever document). This works only for cases where documents have a single-value. Multi-valued docs need to get rolled up after each document to ensure there's no double-counting (see rollupMultiValued(LongRangeNode))
    • rollupMultiValued

      private boolean rollupMultiValued(OverlappingLongRangeCounter.LongRangeNode node)
      Rolls up all the multi-valued doc counts. Note that this is done at the end of each document (as part of endMultiValuedDoc()). All of the counts contributed by a single document get rolled up into the appropriate ranges in this step. It must be done after each document so that counts don't get double-counted, and so we know whether-or-not an individual doc actually contributed to any of the user-requested ranges.
    • buildElementaryIntervals

      private static List<LongRangeCounter.InclusiveRange> buildElementaryIntervals(LongRange[] ranges)