Skip to content

Commit 3b7843d

Browse files
authored
Fix sorting agg buckets by doc_count (#53617)
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 3495239 commit 3b7843d

File tree

3 files changed

+114
-5
lines changed

3 files changed

+114
-5
lines changed

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

Lines changed: 75 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:
@@ -73,3 +73,74 @@ setup:
7373
- match: { _all.total.request_cache.hit_count: 0 }
7474
- match: { _all.total.request_cache.miss_count: 1 }
7575
- is_true: indices.test
76+
77+
---
78+
"As a child of terms":
79+
- do:
80+
bulk:
81+
refresh: true
82+
index: test
83+
body: |
84+
{"index":{}}
85+
{"category": "bar", "val": 8}
86+
{"index":{}}
87+
{"category": "bar", "val": 0}
88+
- do:
89+
search:
90+
size: 0
91+
body:
92+
aggs:
93+
category:
94+
terms:
95+
field: category.keyword
96+
aggs:
97+
high:
98+
filter:
99+
range:
100+
val:
101+
gte: 7
102+
103+
- match: { hits.total.value: 4 }
104+
- match: { aggregations.category.buckets.0.key: bar }
105+
- match: { aggregations.category.buckets.0.doc_count: 2 }
106+
- match: { aggregations.category.buckets.0.high.doc_count: 1 }
107+
108+
---
109+
"Sorting terms":
110+
- do:
111+
bulk:
112+
refresh: true
113+
index: test
114+
body: |
115+
{"index":{}}
116+
{"category": "foo", "val": 7}
117+
{"index":{}}
118+
{"category": "bar", "val": 8}
119+
{"index":{}}
120+
{"category": "bar", "val": 9}
121+
{"index":{}}
122+
{"category": "bar", "val": 0}
123+
- do:
124+
search:
125+
size: 0
126+
body:
127+
aggs:
128+
category:
129+
terms:
130+
field: category.keyword
131+
order:
132+
high.doc_count: desc
133+
aggs:
134+
high:
135+
filter:
136+
range:
137+
val:
138+
gte: 7
139+
140+
- match: { hits.total.value: 6 }
141+
- match: { aggregations.category.buckets.0.key: bar }
142+
- match: { aggregations.category.buckets.0.doc_count: 3 }
143+
- match: { aggregations.category.buckets.0.high.doc_count: 2 }
144+
- match: { aggregations.category.buckets.1.key: foo }
145+
- match: { aggregations.category.buckets.1.doc_count: 1 }
146+
- 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)