|
@@ -58,6 +58,7 @@ import org.elasticsearch.search.internal.SearchContext;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
+import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
@@ -288,7 +289,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
* which is good enough because that is the most embarrassing scenario.
|
|
* which is good enough because that is the most embarrassing scenario.
|
|
*/
|
|
*/
|
|
double averageDocsPerRange = ((double) context.searcher().getIndexReader().maxDoc()) / ranges.length;
|
|
double averageDocsPerRange = ((double) context.searcher().getIndexReader().maxDoc()) / ranges.length;
|
|
- Aggregator adapted = adaptIntoFiltersOrNull(
|
|
|
|
|
|
+ FromFilters<?> adapted = adaptIntoFiltersOrNull(
|
|
name,
|
|
name,
|
|
factories,
|
|
factories,
|
|
valuesSourceConfig,
|
|
valuesSourceConfig,
|
|
@@ -301,8 +302,23 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
cardinality,
|
|
cardinality,
|
|
metadata
|
|
metadata
|
|
);
|
|
);
|
|
|
|
+ Map<String, Object> filtersDebug = null;
|
|
if (adapted != null) {
|
|
if (adapted != null) {
|
|
- return adapted;
|
|
|
|
|
|
+ long maxEstimatedFiltersCost = context.searcher().getIndexReader().maxDoc();
|
|
|
|
+ long estimatedFiltersCost = adapted.estimateCost(maxEstimatedFiltersCost);
|
|
|
|
+ if (estimatedFiltersCost <= maxEstimatedFiltersCost) {
|
|
|
|
+ return adapted;
|
|
|
|
+ }
|
|
|
|
+ /*
|
|
|
|
+ * Looks like it'd be more expensive to use the filter-by-filter
|
|
|
|
+ * aggregator. Oh well. Snapshot the the filter-by-filter
|
|
|
|
+ * aggregator's debug information if we're profiling bececause it
|
|
|
|
+ * is useful even if the aggregator isn't.
|
|
|
|
+ */
|
|
|
|
+ if (context.getProfilers() != null) {
|
|
|
|
+ filtersDebug = new HashMap<>();
|
|
|
|
+ adapted.delegate().collectDebugInfo(filtersDebug::put);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
return buildWithoutAttemptedToAdaptToFilters(
|
|
return buildWithoutAttemptedToAdaptToFilters(
|
|
name,
|
|
name,
|
|
@@ -312,6 +328,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
rangeFactory,
|
|
rangeFactory,
|
|
ranges,
|
|
ranges,
|
|
averageDocsPerRange,
|
|
averageDocsPerRange,
|
|
|
|
+ filtersDebug,
|
|
keyed,
|
|
keyed,
|
|
context,
|
|
context,
|
|
parent,
|
|
parent,
|
|
@@ -320,7 +337,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
- public static Aggregator adaptIntoFiltersOrNull(
|
|
|
|
|
|
+ public static FromFilters<?> adaptIntoFiltersOrNull(
|
|
String name,
|
|
String name,
|
|
AggregatorFactories factories,
|
|
AggregatorFactories factories,
|
|
ValuesSourceConfig valuesSourceConfig,
|
|
ValuesSourceConfig valuesSourceConfig,
|
|
@@ -383,7 +400,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
context.getQueryShardContext()
|
|
context.getQueryShardContext()
|
|
);
|
|
);
|
|
}
|
|
}
|
|
- FiltersAggregator delegate = FiltersAggregator.buildFilterOrderOrNull(
|
|
|
|
|
|
+ FiltersAggregator.FilterByFilter delegate = FiltersAggregator.buildFilterOrderOrNull(
|
|
name,
|
|
name,
|
|
factories,
|
|
factories,
|
|
keys,
|
|
keys,
|
|
@@ -424,6 +441,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
InternalRange.Factory<?, ?> rangeFactory,
|
|
InternalRange.Factory<?, ?> rangeFactory,
|
|
Range[] ranges,
|
|
Range[] ranges,
|
|
double averageDocsPerRange,
|
|
double averageDocsPerRange,
|
|
|
|
+ Map<String, Object> filtersDebug,
|
|
boolean keyed,
|
|
boolean keyed,
|
|
SearchContext context,
|
|
SearchContext context,
|
|
Aggregator parent,
|
|
Aggregator parent,
|
|
@@ -439,6 +457,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
rangeFactory,
|
|
rangeFactory,
|
|
ranges,
|
|
ranges,
|
|
averageDocsPerRange,
|
|
averageDocsPerRange,
|
|
|
|
+ filtersDebug,
|
|
keyed,
|
|
keyed,
|
|
context,
|
|
context,
|
|
parent,
|
|
parent,
|
|
@@ -454,6 +473,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
rangeFactory,
|
|
rangeFactory,
|
|
ranges,
|
|
ranges,
|
|
averageDocsPerRange,
|
|
averageDocsPerRange,
|
|
|
|
+ filtersDebug,
|
|
keyed,
|
|
keyed,
|
|
context,
|
|
context,
|
|
parent,
|
|
parent,
|
|
@@ -468,11 +488,23 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
private final boolean keyed;
|
|
private final boolean keyed;
|
|
private final InternalRange.Factory rangeFactory;
|
|
private final InternalRange.Factory rangeFactory;
|
|
private final double averageDocsPerRange;
|
|
private final double averageDocsPerRange;
|
|
|
|
+ private final Map<String, Object> filtersDebug;
|
|
|
|
|
|
- private RangeAggregator(String name, AggregatorFactories factories, ValuesSource.Numeric valuesSource, DocValueFormat format,
|
|
|
|
- InternalRange.Factory rangeFactory, Range[] ranges, double averageDocsPerRange, boolean keyed, SearchContext context,
|
|
|
|
- Aggregator parent, CardinalityUpperBound cardinality, Map<String, Object> metadata) throws IOException {
|
|
|
|
-
|
|
|
|
|
|
+ private RangeAggregator(
|
|
|
|
+ String name,
|
|
|
|
+ AggregatorFactories factories,
|
|
|
|
+ ValuesSource.Numeric valuesSource,
|
|
|
|
+ DocValueFormat format,
|
|
|
|
+ InternalRange.Factory rangeFactory,
|
|
|
|
+ Range[] ranges,
|
|
|
|
+ double averageDocsPerRange,
|
|
|
|
+ Map<String, Object> filtersDebug,
|
|
|
|
+ boolean keyed,
|
|
|
|
+ SearchContext context,
|
|
|
|
+ Aggregator parent,
|
|
|
|
+ CardinalityUpperBound cardinality,
|
|
|
|
+ Map<String, Object> metadata
|
|
|
|
+ ) throws IOException {
|
|
super(name, factories, context, parent, cardinality.multiply(ranges.length), metadata);
|
|
super(name, factories, context, parent, cardinality.multiply(ranges.length), metadata);
|
|
assert valuesSource != null;
|
|
assert valuesSource != null;
|
|
this.valuesSource = valuesSource;
|
|
this.valuesSource = valuesSource;
|
|
@@ -481,6 +513,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
this.rangeFactory = rangeFactory;
|
|
this.rangeFactory = rangeFactory;
|
|
this.ranges = ranges;
|
|
this.ranges = ranges;
|
|
this.averageDocsPerRange = averageDocsPerRange;
|
|
this.averageDocsPerRange = averageDocsPerRange;
|
|
|
|
+ this.filtersDebug = filtersDebug;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -540,6 +573,9 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
super.collectDebugInfo(add);
|
|
super.collectDebugInfo(add);
|
|
add.accept("ranges", ranges.length);
|
|
add.accept("ranges", ranges.length);
|
|
add.accept("average_docs_per_range", averageDocsPerRange);
|
|
add.accept("average_docs_per_range", averageDocsPerRange);
|
|
|
|
+ if (filtersDebug != null) {
|
|
|
|
+ add.accept("filters_debug", filtersDebug);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
public static class Unmapped<R extends RangeAggregator.Range> extends NonCollectingAggregator {
|
|
public static class Unmapped<R extends RangeAggregator.Range> extends NonCollectingAggregator {
|
|
@@ -591,6 +627,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
Factory rangeFactory,
|
|
Factory rangeFactory,
|
|
Range[] ranges,
|
|
Range[] ranges,
|
|
double averageDocsPerRange,
|
|
double averageDocsPerRange,
|
|
|
|
+ Map<String, Object> filtersDebug,
|
|
boolean keyed,
|
|
boolean keyed,
|
|
SearchContext context,
|
|
SearchContext context,
|
|
Aggregator parent,
|
|
Aggregator parent,
|
|
@@ -605,6 +642,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
rangeFactory,
|
|
rangeFactory,
|
|
ranges,
|
|
ranges,
|
|
averageDocsPerRange,
|
|
averageDocsPerRange,
|
|
|
|
+ filtersDebug,
|
|
keyed,
|
|
keyed,
|
|
context,
|
|
context,
|
|
parent,
|
|
parent,
|
|
@@ -641,6 +679,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
Factory rangeFactory,
|
|
Factory rangeFactory,
|
|
Range[] ranges,
|
|
Range[] ranges,
|
|
double averageDocsPerRange,
|
|
double averageDocsPerRange,
|
|
|
|
+ Map<String, Object> filtersDebug,
|
|
boolean keyed,
|
|
boolean keyed,
|
|
SearchContext context,
|
|
SearchContext context,
|
|
Aggregator parent,
|
|
Aggregator parent,
|
|
@@ -655,6 +694,7 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
rangeFactory,
|
|
rangeFactory,
|
|
ranges,
|
|
ranges,
|
|
averageDocsPerRange,
|
|
averageDocsPerRange,
|
|
|
|
+ filtersDebug,
|
|
keyed,
|
|
keyed,
|
|
context,
|
|
context,
|
|
parent,
|
|
parent,
|
|
@@ -747,6 +787,13 @@ public abstract class RangeAggregator extends BucketsAggregator {
|
|
this.averageDocsPerRange = averageDocsPerRange;
|
|
this.averageDocsPerRange = averageDocsPerRange;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Estimate the number of documents that this aggregation must visit.
|
|
|
|
+ */
|
|
|
|
+ long estimateCost(long maxEstimatedCost) throws IOException {
|
|
|
|
+ return ((FiltersAggregator.FilterByFilter) delegate()).estimateCost(maxEstimatedCost);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
protected InternalAggregation adapt(InternalAggregation delegateResult) {
|
|
protected InternalAggregation adapt(InternalAggregation delegateResult) {
|
|
InternalFilters filters = (InternalFilters) delegateResult;
|
|
InternalFilters filters = (InternalFilters) delegateResult;
|