All Implemented Interfaces:
java.io.Closeable, java.lang.AutoCloseable, org.apache.lucene.search.Collector, org.elasticsearch.common.lease.Releasable

public abstract class RangeAggregator
extends BucketsAggregator
Aggregator for range. There are two known subclasses, RangeAggregator.NoOverlap which is fast but only compatible with ranges that don't have overlaps and RangeAggregator.Overlap which handles overlapping ranges. There is also RangeAggregator.FromFilters which isn't a subclass but is also a functional aggregator for range. build(java.lang.String, org.elasticsearch.search.aggregations.AggregatorFactories, org.elasticsearch.search.aggregations.support.ValuesSourceConfig, org.elasticsearch.search.aggregations.bucket.range.InternalRange.Factory<?, ?>, org.elasticsearch.search.aggregations.bucket.range.RangeAggregator.Range[], boolean, org.elasticsearch.search.aggregations.support.AggregationContext, org.elasticsearch.search.aggregations.Aggregator, org.elasticsearch.search.aggregations.CardinalityUpperBound, java.util.Map<java.lang.String, java.lang.Object>) will build the fastest of the three that is compatible with the requested configuration.
  • Field Details

    • DOCS_PER_RANGE_TO_USE_FILTERS

      public static final double DOCS_PER_RANGE_TO_USE_FILTERS
      Minimum number of docs in the index per range before we attempt to use a filter-based collection mechanism. This exists mostly to keep fast range aggregations fast. Each filter has an overhead in the ball park of half a millisecond just to build its ScorerSupplier. If there are only a couple of thousand docs in the range then it tends not to be worth it to kick in the optimization.

      The value of this field was experimentally derived but the experiment wasn't particularly rigorous. We had a performance test that collected 123 buckets with an average of 900 documents per bucket that jumped from 35ms to 90ms. I figure that 5000 is fairly close to where the break even point is.

      See Also:
      Constant Field Values
    • MAX_ACCURATE_BOUND

      public static final long MAX_ACCURATE_BOUND
      The maximum long that can accurately fit into the double precision floating point bounds.
      See Also:
      Constant Field Values
    • RANGES_FIELD

      public static final org.elasticsearch.common.ParseField RANGES_FIELD
    • KEYED_FIELD

      public static final org.elasticsearch.common.ParseField KEYED_FIELD
    • ranges

      protected final RangeAggregator.Range[] ranges
  • Method Details

    • build

      public static Aggregator build​(java.lang.String name, AggregatorFactories factories, ValuesSourceConfig valuesSourceConfig, InternalRange.Factory<?,​?> rangeFactory, RangeAggregator.Range[] ranges, boolean keyed, AggregationContext context, Aggregator parent, CardinalityUpperBound cardinality, java.util.Map<java.lang.String,​java.lang.Object> metadata) throws java.io.IOException
      Build an Aggregator for a range aggregation. If the ranges can be converted into filters then it builds a FiltersAggregator and uses that to collect the results if that aggregator can run in "filter by filter" collection mode. If it can't then we'll collect the ranges using a native RangeAggregator which is significantly faster than the "compatible" collection mechanism for the filters agg.
      Throws:
      java.io.IOException
    • adaptIntoFiltersOrNull

      public static org.elasticsearch.search.aggregations.bucket.range.RangeAggregator.FromFilters<?> adaptIntoFiltersOrNull​(java.lang.String name, AggregatorFactories factories, ValuesSourceConfig valuesSourceConfig, InternalRange.Factory<?,​?> rangeFactory, RangeAggregator.Range[] ranges, double averageDocsPerRange, boolean keyed, AggregationContext context, Aggregator parent, CardinalityUpperBound cardinality, java.util.Map<java.lang.String,​java.lang.Object> metadata) throws java.io.IOException
      Throws:
      java.io.IOException
    • buildWithoutAttemptedToAdaptToFilters

      public static Aggregator buildWithoutAttemptedToAdaptToFilters​(java.lang.String name, AggregatorFactories factories, ValuesSource.Numeric valuesSource, DocValueFormat format, InternalRange.Factory<?,​?> rangeFactory, RangeAggregator.Range[] ranges, double averageDocsPerRange, java.util.Map<java.lang.String,​java.lang.Object> filtersDebug, boolean keyed, AggregationContext context, Aggregator parent, CardinalityUpperBound cardinality, java.util.Map<java.lang.String,​java.lang.Object> metadata) throws java.io.IOException
      Throws:
      java.io.IOException
    • scoreMode

      public org.apache.lucene.search.ScoreMode scoreMode()
      Description copied from class: AggregatorBase
      Most aggregators don't need scores, make sure to extend this method if your aggregator needs them.
      Specified by:
      scoreMode in interface org.apache.lucene.search.Collector
      Overrides:
      scoreMode in class AggregatorBase
    • getLeafCollector

      public LeafBucketCollector getLeafCollector​(org.apache.lucene.index.LeafReaderContext ctx, LeafBucketCollector sub) throws java.io.IOException
      Description copied from class: AggregatorBase
      Collect results for this leaf.

      Most Aggregators will return a custom LeafBucketCollector that collects document information for every hit. Callers of this method will make sure to call collect for every hit. So any Aggregator that returns a customer LeafBucketCollector from this method runs at best O(hits) time. See the sum Aggregator for a fairly strait forward example of this.

      Some Aggregators are able to correctly collect results on their own, without being iterated by the top level query or the rest of the aggregations framework. These aggregations collect what they need by calling methods on LeafReaderContext and then they return LeafBucketCollector.NO_OP_COLLECTOR to signal that they've done their own collection. These aggregations can do better than O(hits). See the min Aggregator for an example of an aggregation that does this. It happens to run in constant time in some cases.

      In other cases MinAggregator can't get correct results by taking the constant time path so instead it returns a custom LeafBucketCollector. This is fairly common for aggregations that have these fast paths because most of these fast paths are only possible when the aggregation is at the root of the tree.

      Its also useful to look at the filters Aggregator chooses whether or not it can use the fast path before building the Aggregator rather than on each leaf. Either is fine.

      Specified by:
      getLeafCollector in class AggregatorBase
      Throws:
      java.io.IOException
    • subBucketOrdinal

      protected long subBucketOrdinal​(long owningBucketOrdinal, int rangeOrd)
    • buildAggregations

      public InternalAggregation[] buildAggregations​(long[] owningBucketOrds) throws java.io.IOException
      Description copied from class: Aggregator
      Build the results of this aggregation.
      Specified by:
      buildAggregations in class Aggregator
      Parameters:
      owningBucketOrds - the ordinals of the buckets that we want to collect from this aggregation
      Returns:
      the results for each ordinal, in the same order as the array of ordinals
      Throws:
      java.io.IOException
    • buildEmptyAggregation

      public InternalAggregation buildEmptyAggregation()
      Description copied from class: Aggregator
      Build an empty aggregation.
      Specified by:
      buildEmptyAggregation in class Aggregator
    • collectDebugInfo

      public void collectDebugInfo​(java.util.function.BiConsumer<java.lang.String,​java.lang.Object> add)
      Description copied from class: Aggregator
      Collect debug information to add to the profiling results. This will only be called if the aggregation is being profiled.

      Well behaved implementations will always call the superclass implementation just in case it has something interesting. They will also only add objects which can be serialized with StreamOutput.writeGenericValue(Object) and XContentBuilder.value(Object). And they'll have an integration test.

      Overrides:
      collectDebugInfo in class Aggregator
    • collect

      protected abstract int collect​(LeafBucketCollector sub, int doc, double value, long owningBucketOrdinal, int lowBound) throws java.io.IOException
      Throws:
      java.io.IOException