Skip to content

Commit c7cb3d6

Browse files
committed
Aggregations: the children agg didn't take deleted document into account.
The live docs that is passed down was ignored by the filter impl. Now the children filter gets wrapped with ApplyAcceptedDocsFilter, so live docs are actually applied. Closes #8180
1 parent 2a0d9b5 commit c7cb3d6

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/main/java/org/elasticsearch/search/aggregations/bucket/children/ParentToChildrenAggregator.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.elasticsearch.common.lease.Releasables;
3030
import org.elasticsearch.common.lucene.ReaderContextAware;
3131
import org.elasticsearch.common.lucene.docset.DocIdSets;
32+
import org.elasticsearch.common.lucene.search.ApplyAcceptedDocsFilter;
3233
import org.elasticsearch.common.util.LongArray;
3334
import org.elasticsearch.common.util.LongObjectPagedHashMap;
3435
import org.elasticsearch.index.cache.fixedbitset.FixedBitSetFilter;
@@ -52,7 +53,7 @@
5253
public class ParentToChildrenAggregator extends SingleBucketAggregator implements ReaderContextAware {
5354

5455
private final String parentType;
55-
private final FixedBitSetFilter childFilter;
56+
private final Filter childFilter;
5657
private final FixedBitSetFilter parentFilter;
5758
private final ValuesSource.Bytes.WithOrdinals.ParentChild valuesSource;
5859

@@ -75,7 +76,10 @@ public ParentToChildrenAggregator(String name, AggregatorFactories factories, Ag
7576
ValuesSource.Bytes.WithOrdinals.ParentChild valuesSource, long maxOrd) {
7677
super(name, factories, aggregationContext, parent);
7778
this.parentType = parentType;
78-
this.childFilter = aggregationContext.searchContext().fixedBitSetFilterCache().getFixedBitSetFilter(childFilter);
79+
// The child filter doesn't rely on random access it just used to iterate over all docs with a specific type,
80+
// so use the filter cache instead. When the filter cache is smarter with what filter impl to pick we can benefit
81+
// from it here
82+
this.childFilter = new ApplyAcceptedDocsFilter(aggregationContext.searchContext().filterCache().cache(childFilter));
7983
this.parentFilter = aggregationContext.searchContext().fixedBitSetFilterCache().getFixedBitSetFilter(parentFilter);
8084
this.parentOrdToBuckets = aggregationContext.bigArrays().newLongArray(maxOrd, false);
8185
this.parentOrdToBuckets.fill(0, maxOrd, -1);

src/test/java/org/elasticsearch/search/aggregations/bucket/ChildrenTests.java

+43
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020

2121
import org.elasticsearch.action.index.IndexRequestBuilder;
2222
import org.elasticsearch.action.search.SearchResponse;
23+
import org.elasticsearch.action.update.UpdateResponse;
2324
import org.elasticsearch.search.SearchHit;
2425
import org.elasticsearch.search.aggregations.bucket.children.Children;
2526
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
27+
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
2628
import org.elasticsearch.search.aggregations.metrics.tophits.TopHits;
2729
import org.elasticsearch.search.sort.SortOrder;
2830
import org.elasticsearch.test.ElasticsearchIntegrationTest;
@@ -33,8 +35,10 @@
3335
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
3436
import static org.elasticsearch.search.aggregations.AggregationBuilders.*;
3537
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
38+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
3639
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
3740
import static org.hamcrest.Matchers.equalTo;
41+
import static org.hamcrest.Matchers.greaterThan;
3842
import static org.hamcrest.Matchers.is;
3943

4044
/**
@@ -215,6 +219,45 @@ public void testParentWithMultipleBuckets() throws Exception {
215219
assertThat(topHits.getHits().getAt(0).getType(), equalTo("comment"));
216220
}
217221

222+
@Test
223+
public void testWithDeletes() throws Exception {
224+
String indexName = "xyz";
225+
assertAcked(
226+
prepareCreate(indexName)
227+
.addMapping("parent")
228+
.addMapping("child", "_parent", "type=parent", "count", "type=long")
229+
);
230+
231+
List<IndexRequestBuilder> requests = new ArrayList<>();
232+
requests.add(client().prepareIndex(indexName, "parent", "1").setSource("{}"));
233+
requests.add(client().prepareIndex(indexName, "child", "0").setParent("1").setSource("count", 1));
234+
requests.add(client().prepareIndex(indexName, "child", "1").setParent("1").setSource("count", 1));
235+
requests.add(client().prepareIndex(indexName, "child", "2").setParent("1").setSource("count", 1));
236+
requests.add(client().prepareIndex(indexName, "child", "3").setParent("1").setSource("count", 1));
237+
indexRandom(true, requests);
238+
239+
for (int i = 0; i < 10; i++) {
240+
SearchResponse searchResponse = client().prepareSearch(indexName)
241+
.addAggregation(children("children").childType("child").subAggregation(sum("counts").field("count")))
242+
.get();
243+
244+
assertNoFailures(searchResponse);
245+
Children children = searchResponse.getAggregations().get("children");
246+
assertThat(children.getDocCount(), equalTo(4l));
247+
248+
Sum count = children.getAggregations().get("counts");
249+
assertThat(count.getValue(), equalTo(4.));
250+
251+
String idToUpdate = Integer.toString(randomInt(3));
252+
UpdateResponse updateResponse = client().prepareUpdate(indexName, "child", idToUpdate)
253+
.setParent("1")
254+
.setDoc("count", 1)
255+
.get();
256+
assertThat(updateResponse.getVersion(), greaterThan(1l));
257+
refresh();
258+
}
259+
}
260+
218261
private static final class Control {
219262

220263
final String category;

0 commit comments

Comments
 (0)