Skip to content

Commit 617d9d8

Browse files
committed
Handles exists query in composite aggs (#35758)
This commit adds the support for exists query in the sorted execution mode of the `composite` aggregation. We'll execute the aggregation from the sorted points and use early termination if the main query is an `exists` query over the first source of the `composite` aggregation.
1 parent bfbf134 commit 617d9d8

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/LongValuesSource.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.apache.lucene.index.LeafReaderContext;
2626
import org.apache.lucene.index.SortedNumericDocValues;
2727
import org.apache.lucene.search.BoostQuery;
28+
import org.apache.lucene.search.ConstantScoreQuery;
29+
import org.apache.lucene.search.DocValuesFieldExistsQuery;
2830
import org.apache.lucene.search.IndexOrDocValuesQuery;
2931
import org.apache.lucene.search.MatchAllDocsQuery;
3032
import org.apache.lucene.search.PointRangeQuery;
@@ -180,24 +182,42 @@ public void collect(int doc, long bucket) throws IOException {
180182
};
181183
}
182184

183-
static Query extractQuery(Query query) {
185+
private static Query extractQuery(Query query) {
184186
if (query instanceof BoostQuery) {
185187
return extractQuery(((BoostQuery) query).getQuery());
186188
} else if (query instanceof IndexOrDocValuesQuery) {
187189
return extractQuery(((IndexOrDocValuesQuery) query).getIndexQuery());
190+
} else if (query instanceof ConstantScoreQuery){
191+
return extractQuery(((ConstantScoreQuery) query).getQuery());
188192
} else {
189193
return query;
190194
}
191195
}
192196

197+
/**
198+
* Returns true if we can use <code>query</code> with a {@link SortedDocsProducer} on <code>fieldName</code>.
199+
*/
200+
private static boolean checkMatchAllOrRangeQuery(Query query, String fieldName) {
201+
if (query == null) {
202+
return true;
203+
} else if (query.getClass() == MatchAllDocsQuery.class) {
204+
return true;
205+
} else if (query instanceof PointRangeQuery) {
206+
PointRangeQuery pointQuery = (PointRangeQuery) query;
207+
return fieldName.equals(pointQuery.getField());
208+
} else if (query instanceof DocValuesFieldExistsQuery) {
209+
DocValuesFieldExistsQuery existsQuery = (DocValuesFieldExistsQuery) query;
210+
return fieldName.equals(existsQuery.getField());
211+
} else {
212+
return false;
213+
}
214+
}
215+
193216
@Override
194217
SortedDocsProducer createSortedDocsProducerOrNull(IndexReader reader, Query query) {
195218
query = extractQuery(query);
196219
if (checkIfSortedDocsIsApplicable(reader, fieldType) == false ||
197-
(query != null &&
198-
query.getClass() != MatchAllDocsQuery.class &&
199-
// if the query is a range query over the same field
200-
(query instanceof PointRangeQuery && fieldType.name().equals((((PointRangeQuery) query).getField()))) == false)) {
220+
checkMatchAllOrRangeQuery(query, fieldType.name()) == false) {
201221
return null;
202222
}
203223
final byte[] lowerPoint;

server/src/test/java/org/elasticsearch/search/aggregations/bucket/composite/SingleDimensionValuesSourceTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.apache.lucene.index.IndexReader;
2424
import org.apache.lucene.index.Term;
2525
import org.apache.lucene.search.BoostQuery;
26+
import org.apache.lucene.search.ConstantScoreQuery;
27+
import org.apache.lucene.search.DocValuesFieldExistsQuery;
2628
import org.apache.lucene.search.IndexOrDocValuesQuery;
2729
import org.apache.lucene.search.MatchAllDocsQuery;
2830
import org.apache.lucene.search.TermQuery;
@@ -56,6 +58,7 @@ public void testBinarySorted() {
5658
IndexReader reader = mockIndexReader(1, 1);
5759
assertNotNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
5860
assertNotNull(source.createSortedDocsProducerOrNull(reader, null));
61+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
5962
assertNull(source.createSortedDocsProducerOrNull(reader,
6063
new TermQuery(new Term("keyword", "toto)"))));
6164

@@ -131,6 +134,7 @@ public void testGlobalOrdinalsSorted() {
131134
IndexReader reader = mockIndexReader(1, 1);
132135
assertNotNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
133136
assertNotNull(source.createSortedDocsProducerOrNull(reader, null));
137+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
134138
assertNull(source.createSortedDocsProducerOrNull(reader,
135139
new TermQuery(new Term("keyword", "toto)"))));
136140

@@ -159,6 +163,7 @@ public void testGlobalOrdinalsSorted() {
159163
);
160164
assertNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
161165
assertNull(source.createSortedDocsProducerOrNull(reader, null));
166+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
162167

163168
source = new GlobalOrdinalValuesSource(
164169
BigArrays.NON_RECYCLING_INSTANCE,
@@ -171,6 +176,7 @@ public void testGlobalOrdinalsSorted() {
171176
-1
172177
);
173178
assertNull(source.createSortedDocsProducerOrNull(reader, null));
179+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
174180

175181
final MappedFieldType ip = new IpFieldMapper.IpFieldType();
176182
ip.setName("ip");
@@ -185,6 +191,7 @@ public void testGlobalOrdinalsSorted() {
185191
1
186192
);
187193
assertNull(source.createSortedDocsProducerOrNull(reader, null));
194+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
188195
}
189196

190197
public void testNumericSorted() {
@@ -215,6 +222,9 @@ public void testNumericSorted() {
215222
assertNotNull(source.createSortedDocsProducerOrNull(reader, LongPoint.newRangeQuery("number", 0, 1)));
216223
assertNotNull(source.createSortedDocsProducerOrNull(reader, new IndexOrDocValuesQuery(
217224
LongPoint.newRangeQuery("number", 0, 1), new MatchAllDocsQuery())));
225+
assertNotNull(source.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
226+
assertNotNull(source.createSortedDocsProducerOrNull(reader,
227+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
218228
assertNotNull(source.createSortedDocsProducerOrNull(reader, new BoostQuery(new IndexOrDocValuesQuery(
219229
LongPoint.newRangeQuery("number", 0, 1), new MatchAllDocsQuery()), 2.0f)));
220230
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
@@ -246,6 +256,9 @@ public void testNumericSorted() {
246256
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
247257
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, null));
248258
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
259+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
260+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader,
261+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
249262

250263
LongValuesSource sourceRev = new LongValuesSource(
251264
BigArrays.NON_RECYCLING_INSTANCE,
@@ -259,6 +272,10 @@ public void testNumericSorted() {
259272
-1
260273
);
261274
assertNull(sourceRev.createSortedDocsProducerOrNull(reader, null));
275+
assertNull(sourceRev.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
276+
assertNull(sourceRev.createSortedDocsProducerOrNull(reader,
277+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
278+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
262279
} else if (numberType == NumberFieldMapper.NumberType.HALF_FLOAT ||
263280
numberType == NumberFieldMapper.NumberType.FLOAT ||
264281
numberType == NumberFieldMapper.NumberType.DOUBLE) {
@@ -274,6 +291,10 @@ public void testNumericSorted() {
274291
);
275292
IndexReader reader = mockIndexReader(1, 1);
276293
assertNull(source.createSortedDocsProducerOrNull(reader, null));
294+
assertNull(source.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
295+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
296+
assertNull(source.createSortedDocsProducerOrNull(reader,
297+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
277298
} else{
278299
throw new AssertionError ("missing type:" + numberType.typeName());
279300
}

0 commit comments

Comments
 (0)