Now that we're consistently using `cat_match` to filter which shards we run on we can get this confusing case: 1. You have a search with, say, a range and a sub-agg. 2. That search has a query that `can_match` can recognize will match no docs. On *any* shard. 3. So we dutifully run it on a single shard so it can produce the "empty" aggs. 4. The shard we pick happens to not have the target of the range mapped. 5. This kicks in the special range aggregator that doesn't collect any documents. 6. Before this commit, that range aggregator *also* never produced any sub-aggs. So, without this change, it was quite possible for a search that happened to match no documents to "throw away" the sub-aggs of a range and a few other aggs. We've had this problem for a long, long time but it is more confusing now because `can_match` is really kicking in and causing us to see cases where it looks like you are targeting a lot of shards but you really are only targeting a couple. It used to be that to get the "no sub-aggs" behavior you had to explicitly target only shards that didn't map the target field of the `range` agg. And, like, in that case it isn't too bad because you targeted a sort of degenerate shard. But now that `can_match` is doing its thing you can end up with the confusing steps above. It took me several hours to track down what what happening I know how the individual pieces of all of this works. It took four hours to figure out how they fit together in this case.... Anyway! This replaces all the aggregator implementations that throw out the sub-aggregators with ones that keep them. I think this'll be less confusing in the future. Closes #64142
This commit is contained in:
parent
78c741ab32
commit
0c47d49784
|
@ -60,7 +60,7 @@ public class ChildrenAggregatorFactory extends ValuesSourceAggregatorFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Aggregator createUnmapped(SearchContext searchContext, Aggregator parent, Map<String, Object> metadata) throws IOException {
|
protected Aggregator createUnmapped(SearchContext searchContext, Aggregator parent, Map<String, Object> metadata) throws IOException {
|
||||||
return new NonCollectingAggregator(name, searchContext, parent, metadata) {
|
return new NonCollectingAggregator(name, searchContext, parent, factories, metadata) {
|
||||||
@Override
|
@Override
|
||||||
public InternalAggregation buildEmptyAggregation() {
|
public InternalAggregation buildEmptyAggregation() {
|
||||||
return new InternalChildren(name, 0, buildEmptySubAggregations(), metadata());
|
return new InternalChildren(name, 0, buildEmptySubAggregations(), metadata());
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class ParentAggregatorFactory extends ValuesSourceAggregatorFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Aggregator createUnmapped(SearchContext searchContext, Aggregator parent, Map<String, Object> metadata) throws IOException {
|
protected Aggregator createUnmapped(SearchContext searchContext, Aggregator parent, Map<String, Object> metadata) throws IOException {
|
||||||
return new NonCollectingAggregator(name, searchContext, parent, metadata) {
|
return new NonCollectingAggregator(name, searchContext, parent, factories, metadata) {
|
||||||
@Override
|
@Override
|
||||||
public InternalAggregation buildEmptyAggregation() {
|
public InternalAggregation buildEmptyAggregation() {
|
||||||
return new InternalParent(name, 0, buildEmptySubAggregations(), metadata());
|
return new InternalParent(name, 0, buildEmptySubAggregations(), metadata());
|
||||||
|
|
|
@ -387,3 +387,43 @@ setup:
|
||||||
- match: { aggregations.age_groups.buckets.2.key: "Generation Y" }
|
- match: { aggregations.age_groups.buckets.2.key: "Generation Y" }
|
||||||
|
|
||||||
- match: { aggregations.age_groups.buckets.2.doc_count: 2 }
|
- match: { aggregations.age_groups.buckets.2.doc_count: 2 }
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
"Date range unmapped with children":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.9.99"
|
||||||
|
reason: Fixed in 7.10.0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.create:
|
||||||
|
index: test_a_unmapped
|
||||||
|
body:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
index: test_a_unmapped
|
||||||
|
body:
|
||||||
|
size: 0
|
||||||
|
query:
|
||||||
|
terms:
|
||||||
|
animal: []
|
||||||
|
aggs:
|
||||||
|
date_range:
|
||||||
|
date_range:
|
||||||
|
field: date
|
||||||
|
ranges:
|
||||||
|
- from: 2020-01-01T00:00:00Z
|
||||||
|
aggs:
|
||||||
|
sounds:
|
||||||
|
cardinality:
|
||||||
|
field: sound.keyword
|
||||||
|
|
||||||
|
- match: { hits.total.value: 0 }
|
||||||
|
- length: { aggregations.date_range.buckets: 1 }
|
||||||
|
- match: { aggregations.date_range.buckets.0.doc_count: 0 }
|
||||||
|
- match: { aggregations.date_range.buckets.0.key: "2020-01-01T00:00:00.000Z-*" }
|
||||||
|
- is_false: aggregations.date_range.buckets.0.to
|
||||||
|
- match: { aggregations.date_range.buckets.0.sounds.value: 0 }
|
||||||
|
|
|
@ -38,14 +38,6 @@ public abstract class NonCollectingAggregator extends AggregatorBase {
|
||||||
super(name, subFactories, context, parent, CardinalityUpperBound.NONE, metadata);
|
super(name, subFactories, context, parent, CardinalityUpperBound.NONE, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a {@linkplain NonCollectingAggregator} for an aggregator without sub-aggregators.
|
|
||||||
*/
|
|
||||||
protected NonCollectingAggregator(String name, SearchContext context, Aggregator parent,
|
|
||||||
Map<String, Object> metadata) throws IOException {
|
|
||||||
this(name, context, parent, AggregatorFactories.EMPTY, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final LeafBucketCollector getLeafCollector(LeafReaderContext reader, LeafBucketCollector sub) {
|
public final LeafBucketCollector getLeafCollector(LeafReaderContext reader, LeafBucketCollector sub) {
|
||||||
// the framework will automatically eliminate it
|
// the framework will automatically eliminate it
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class GeoHashGridAggregatorFactory extends ValuesSourceAggregatorFactory
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
final InternalAggregation aggregation = new InternalGeoHashGrid(name, requiredSize, emptyList(), metadata);
|
final InternalAggregation aggregation = new InternalGeoHashGrid(name, requiredSize, emptyList(), metadata);
|
||||||
return new NonCollectingAggregator(name, searchContext, parent, metadata) {
|
return new NonCollectingAggregator(name, searchContext, parent, factories, metadata) {
|
||||||
@Override
|
@Override
|
||||||
public InternalAggregation buildEmptyAggregation() {
|
public InternalAggregation buildEmptyAggregation() {
|
||||||
return aggregation;
|
return aggregation;
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class GeoTileGridAggregatorFactory extends ValuesSourceAggregatorFactory
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
final InternalAggregation aggregation = new InternalGeoTileGrid(name, requiredSize, Collections.emptyList(), metadata);
|
final InternalAggregation aggregation = new InternalGeoTileGrid(name, requiredSize, Collections.emptyList(), metadata);
|
||||||
return new NonCollectingAggregator(name, searchContext, parent, metadata) {
|
return new NonCollectingAggregator(name, searchContext, parent, factories, metadata) {
|
||||||
@Override
|
@Override
|
||||||
public InternalAggregation buildEmptyAggregation() {
|
public InternalAggregation buildEmptyAggregation() {
|
||||||
return aggregation;
|
return aggregation;
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class NestedAggregatorFactory extends AggregatorFactory {
|
||||||
CardinalityUpperBound cardinality,
|
CardinalityUpperBound cardinality,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
if (childObjectMapper == null) {
|
if (childObjectMapper == null) {
|
||||||
return new Unmapped(name, searchContext, parent, metadata);
|
return new Unmapped(name, searchContext, parent, factories, metadata);
|
||||||
}
|
}
|
||||||
return new NestedAggregator(name, factories, parentObjectMapper, childObjectMapper, searchContext, parent,
|
return new NestedAggregator(name, factories, parentObjectMapper, childObjectMapper, searchContext, parent,
|
||||||
cardinality, metadata);
|
cardinality, metadata);
|
||||||
|
@ -62,8 +62,9 @@ public class NestedAggregatorFactory extends AggregatorFactory {
|
||||||
Unmapped(String name,
|
Unmapped(String name,
|
||||||
SearchContext context,
|
SearchContext context,
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
|
AggregatorFactories factories,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
super(name, context, parent, metadata);
|
super(name, context, parent, factories, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class ReverseNestedAggregatorFactory extends AggregatorFactory {
|
||||||
CardinalityUpperBound cardinality,
|
CardinalityUpperBound cardinality,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
if (unmapped) {
|
if (unmapped) {
|
||||||
return new Unmapped(name, searchContext, parent, metadata);
|
return new Unmapped(name, searchContext, parent, factories, metadata);
|
||||||
} else {
|
} else {
|
||||||
return new ReverseNestedAggregator(name, factories, parentObjectMapper,
|
return new ReverseNestedAggregator(name, factories, parentObjectMapper,
|
||||||
searchContext, parent, cardinality, metadata);
|
searchContext, parent, cardinality, metadata);
|
||||||
|
@ -64,8 +64,9 @@ public class ReverseNestedAggregatorFactory extends AggregatorFactory {
|
||||||
Unmapped(String name,
|
Unmapped(String name,
|
||||||
SearchContext context,
|
SearchContext context,
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
|
AggregatorFactories factories,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
super(name, context, parent, metadata);
|
super(name, context, parent, factories, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class AbstractRangeAggregatorFactory<R extends Range> extends ValuesSourc
|
||||||
protected Aggregator createUnmapped(SearchContext searchContext,
|
protected Aggregator createUnmapped(SearchContext searchContext,
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
return new Unmapped<>(name, ranges, keyed, config.format(), searchContext, parent, rangeFactory, metadata);
|
return new Unmapped<>(name, factories, ranges, keyed, config.format(), searchContext, parent, rangeFactory, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class GeoDistanceRangeAggregatorFactory extends ValuesSourceAggregatorFac
|
||||||
protected Aggregator createUnmapped(SearchContext searchContext,
|
protected Aggregator createUnmapped(SearchContext searchContext,
|
||||||
Aggregator parent,
|
Aggregator parent,
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
return new RangeAggregator.Unmapped<>(name, ranges, keyed, config.format(), searchContext, parent,
|
return new RangeAggregator.Unmapped<>(name, factories, ranges, keyed, config.format(), searchContext, parent,
|
||||||
rangeFactory, metadata);
|
rangeFactory, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,11 +353,19 @@ public class RangeAggregator extends BucketsAggregator {
|
||||||
private final InternalRange.Factory factory;
|
private final InternalRange.Factory factory;
|
||||||
private final DocValueFormat format;
|
private final DocValueFormat format;
|
||||||
|
|
||||||
public Unmapped(String name, R[] ranges, boolean keyed, DocValueFormat format, SearchContext context, Aggregator parent,
|
public Unmapped(
|
||||||
InternalRange.Factory factory, Map<String, Object> metadata)
|
String name,
|
||||||
throws IOException {
|
AggregatorFactories factories,
|
||||||
|
R[] ranges,
|
||||||
|
boolean keyed,
|
||||||
|
DocValueFormat format,
|
||||||
|
SearchContext context,
|
||||||
|
Aggregator parent,
|
||||||
|
InternalRange.Factory factory,
|
||||||
|
Map<String, Object> metadata
|
||||||
|
) throws IOException {
|
||||||
|
|
||||||
super(name, context, parent, metadata);
|
super(name, context, parent, factories, metadata);
|
||||||
this.ranges = ranges;
|
this.ranges = ranges;
|
||||||
this.keyed = keyed;
|
this.keyed = keyed;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
|
|
|
@ -186,7 +186,7 @@ public class SignificantTermsAggregatorFactory extends ValuesSourceAggregatorFac
|
||||||
Map<String, Object> metadata) throws IOException {
|
Map<String, Object> metadata) throws IOException {
|
||||||
final InternalAggregation aggregation = new UnmappedSignificantTerms(name, bucketCountThresholds.getRequiredSize(),
|
final InternalAggregation aggregation = new UnmappedSignificantTerms(name, bucketCountThresholds.getRequiredSize(),
|
||||||
bucketCountThresholds.getMinDocCount(), metadata);
|
bucketCountThresholds.getMinDocCount(), metadata);
|
||||||
return new NonCollectingAggregator(name, searchContext, parent, metadata) {
|
return new NonCollectingAggregator(name, searchContext, parent, factories, metadata) {
|
||||||
@Override
|
@Override
|
||||||
public InternalAggregation buildEmptyAggregation() {
|
public InternalAggregation buildEmptyAggregation() {
|
||||||
return aggregation;
|
return aggregation;
|
||||||
|
|
Loading…
Reference in New Issue