From ed2c29f102c79e8122ed0d3880881d1a37f14fcf Mon Sep 17 00:00:00 2001 From: Mark Tozzi Date: Tue, 14 Jul 2020 16:56:29 -0400 Subject: [PATCH] If no perBucketSample has been allocated for the parent bucket return a doc count of 0 (#59360) (#59567) Co-authored-by: Fabio Corneti --- .../sampler/BestDocsDeferringCollector.java | 3 ++ .../sampler/SamplerAggregatorTests.java | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/BestDocsDeferringCollector.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/BestDocsDeferringCollector.java index 47174089cd5..bc581551b3c 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/BestDocsDeferringCollector.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/sampler/BestDocsDeferringCollector.java @@ -306,6 +306,9 @@ public class BestDocsDeferringCollector extends DeferringBucketCollector impleme } public int getDocCount(long parentBucket) { + if (perBucketSamples.size() <= parentBucket) { + return 0; + } PerParentBucketSamples sampler = perBucketSamples.get((int) parentBucket); if (sampler == null) { // There are conditions where no docs are collected and the aggs diff --git a/server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/SamplerAggregatorTests.java b/server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/SamplerAggregatorTests.java index 4d4ee292ebb..0ea6fd172d1 100644 --- a/server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/SamplerAggregatorTests.java +++ b/server/src/test/java/org/elasticsearch/search/aggregations/bucket/sampler/SamplerAggregatorTests.java @@ -28,13 +28,20 @@ import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.store.Directory; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.NumberFieldMapper; import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType; +import org.elasticsearch.index.query.MatchAllQueryBuilder; +import org.elasticsearch.index.query.MatchNoneQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.aggregations.AggregatorTestCase; +import org.elasticsearch.search.aggregations.bucket.filter.FiltersAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.filter.InternalFilters; +import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; import org.elasticsearch.search.aggregations.metrics.Min; import org.elasticsearch.search.aggregations.metrics.MinAggregationBuilder; import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper; @@ -117,4 +124,36 @@ public class SamplerAggregatorTests extends AggregatorTestCase { } } } + + /** + * Tests that the sampler aggregation works correctly if the parent bucket does not contain any hit. + */ + public void testEmptyParentBucket() throws Exception { + IndexWriterConfig indexWriterConfig = newIndexWriterConfig(); + try (Directory dir = newDirectory(); + IndexWriter writer = new IndexWriter(dir, indexWriterConfig)) { + + writer.addDocument(new Document()); + + try (IndexReader reader = DirectoryReader.open(writer)) { + IndexSearcher searcher = new IndexSearcher(reader); + + QueryBuilder[] filters = new QueryBuilder[]{ + new MatchAllQueryBuilder(), + new MatchNoneQueryBuilder() + }; + FiltersAggregationBuilder samplerParent = new FiltersAggregationBuilder("filters", filters); + TermsAggregationBuilder samplerChild = new TermsAggregationBuilder("child").field("field"); + SamplerAggregationBuilder sampler = new SamplerAggregationBuilder("sampler") + .subAggregation(samplerChild); + samplerParent.subAggregation(sampler); + + InternalFilters response = searchAndReduce(searcher, new MatchAllDocsQuery(), samplerParent); + assertEquals(response.getBuckets().size(), 2); + assertEquals(response.getBuckets().get(0).getDocCount(), 1); + assertEquals(response.getBuckets().get(1).getDocCount(), 0); + } + } + } + }