Skip to content

Commit 9845dbb

Browse files
authored
Fix sorting agg buckets by doc_count (backport of #53617) (#53627)
I broke sorting aggregations by `doc_count` in #51271 by mixing up true and false. This flips that comparison and adds a few tests to double check that we don't so this again.
1 parent b4e203a commit 9845dbb

File tree

3 files changed

+122
-5
lines changed

3 files changed

+122
-5
lines changed

rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/50_filter.yml

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ setup:
1414
type: keyword
1515

1616
- do:
17-
index:
18-
index: test
19-
id: foo|bar|baz0
20-
body: { "notifications" : ["abc"] }
17+
index:
18+
index: test
19+
id: foo|bar|baz0
20+
body: { "notifications" : ["abc"] }
2121

2222
- do:
2323
index:
@@ -75,3 +75,82 @@ setup:
7575
- match: { _all.total.request_cache.hit_count: 0 }
7676
- match: { _all.total.request_cache.miss_count: 1 }
7777
- is_true: indices.test
78+
79+
---
80+
"As a child of terms":
81+
- skip:
82+
version: " - 6.99.99"
83+
reason: the test is written for hits.total.value
84+
85+
- do:
86+
bulk:
87+
refresh: true
88+
index: test
89+
body: |
90+
{"index":{}}
91+
{"category": "bar", "val": 8}
92+
{"index":{}}
93+
{"category": "bar", "val": 0}
94+
- do:
95+
search:
96+
size: 0
97+
body:
98+
aggs:
99+
category:
100+
terms:
101+
field: category.keyword
102+
aggs:
103+
high:
104+
filter:
105+
range:
106+
val:
107+
gte: 7
108+
109+
- match: { hits.total.value: 4 }
110+
- match: { aggregations.category.buckets.0.key: bar }
111+
- match: { aggregations.category.buckets.0.doc_count: 2 }
112+
- match: { aggregations.category.buckets.0.high.doc_count: 1 }
113+
114+
---
115+
"Sorting terms":
116+
- skip:
117+
version: " - 7.6.99"
118+
reason: fixed in 7.7.0
119+
120+
- do:
121+
bulk:
122+
refresh: true
123+
index: test
124+
body: |
125+
{"index":{}}
126+
{"category": "foo", "val": 7}
127+
{"index":{}}
128+
{"category": "bar", "val": 8}
129+
{"index":{}}
130+
{"category": "bar", "val": 9}
131+
{"index":{}}
132+
{"category": "bar", "val": 0}
133+
- do:
134+
search:
135+
size: 0
136+
body:
137+
aggs:
138+
category:
139+
terms:
140+
field: category.keyword
141+
order:
142+
high.doc_count: desc
143+
aggs:
144+
high:
145+
filter:
146+
range:
147+
val:
148+
gte: 7
149+
150+
- match: { hits.total.value: 6 }
151+
- match: { aggregations.category.buckets.0.key: bar }
152+
- match: { aggregations.category.buckets.0.doc_count: 3 }
153+
- match: { aggregations.category.buckets.0.high.doc_count: 2 }
154+
- match: { aggregations.category.buckets.1.key: foo }
155+
- match: { aggregations.category.buckets.1.doc_count: 1 }
156+
- match: { aggregations.category.buckets.1.high.doc_count: 1 }

server/src/main/java/org/elasticsearch/search/aggregations/bucket/BucketsAggregator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public Aggregator resolveSortPath(AggregationPath.PathElement next, Iterator<Agg
176176

177177
@Override
178178
public BucketComparator bucketComparator(String key, SortOrder order) {
179-
if (key == null || false == "doc_count".equals(key)) {
179+
if (key == null || "doc_count".equals(key)) {
180180
return (lhs, rhs) -> order.reverseMul() * Integer.compare(bucketDocCount(lhs), bucketDocCount(rhs));
181181
}
182182
throw new IllegalArgumentException("Ordering on a single-bucket aggregation can only be done on its doc_count. " +

server/src/test/java/org/elasticsearch/search/aggregations/bucket/filter/FilterAggregatorTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,23 @@
2929
import org.apache.lucene.store.Directory;
3030
import org.elasticsearch.index.mapper.KeywordFieldMapper;
3131
import org.elasticsearch.index.mapper.MappedFieldType;
32+
import org.elasticsearch.index.query.MatchAllQueryBuilder;
3233
import org.elasticsearch.index.query.QueryBuilder;
3334
import org.elasticsearch.index.query.QueryBuilders;
35+
import org.elasticsearch.search.aggregations.Aggregator.BucketComparator;
3436
import org.elasticsearch.search.aggregations.AggregatorTestCase;
37+
import org.elasticsearch.search.aggregations.LeafBucketCollector;
3538
import org.elasticsearch.search.aggregations.support.AggregationInspectionHelper;
39+
import org.elasticsearch.search.sort.SortOrder;
3640
import org.junit.Before;
3741

42+
import java.io.IOException;
43+
44+
import static java.util.Collections.singleton;
45+
import static org.hamcrest.Matchers.equalTo;
46+
import static org.hamcrest.Matchers.greaterThan;
47+
import static org.hamcrest.Matchers.lessThan;
48+
3849
public class FilterAggregatorTests extends AggregatorTestCase {
3950
private MappedFieldType fieldType;
4051

@@ -110,6 +121,33 @@ public void testRandom() throws Exception {
110121
indexReader.close();
111122
directory.close();
112123
}
124+
}
113125

126+
public void testBucketComparator() throws IOException {
127+
try (Directory directory = newDirectory()) {
128+
try (RandomIndexWriter indexWriter = new RandomIndexWriter(random(), directory)) {
129+
indexWriter.addDocument(singleton(new Field("field", "1", fieldType)));
130+
}
131+
try (IndexReader indexReader = DirectoryReader.open(directory)) {
132+
IndexSearcher indexSearcher = newSearcher(indexReader, true, true);
133+
FilterAggregationBuilder builder = new FilterAggregationBuilder("test", new MatchAllQueryBuilder());
134+
FilterAggregator agg = createAggregator(builder, indexSearcher, fieldType);
135+
agg.preCollection();
136+
LeafBucketCollector collector = agg.getLeafCollector(indexReader.leaves().get(0));
137+
collector.collect(0, 0);
138+
collector.collect(0, 0);
139+
collector.collect(0, 1);
140+
BucketComparator c = agg.bucketComparator(null, SortOrder.ASC);
141+
assertThat(c.compare(0, 1), greaterThan(0));
142+
assertThat(c.compare(1, 0), lessThan(0));
143+
c = agg.bucketComparator("doc_count", SortOrder.ASC);
144+
assertThat(c.compare(0, 1), greaterThan(0));
145+
assertThat(c.compare(1, 0), lessThan(0));
146+
Exception e = expectThrows(IllegalArgumentException.class, () ->
147+
agg.bucketComparator("garbage", randomFrom(SortOrder.values())));
148+
assertThat(e.getMessage(), equalTo("Ordering on a single-bucket aggregation can only be done on its doc_count. "
149+
+ "Either drop the key (a la \"test\") or change it to \"doc_count\" (a la \"test.doc_count\") or \"key\"."));
150+
}
151+
}
114152
}
115153
}

0 commit comments

Comments
 (0)