Skip to content

Commit 900caa2

Browse files
authored
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 3f7cae3 commit 900caa2

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;
@@ -55,6 +57,7 @@ public void testBinarySorted() {
5557
IndexReader reader = mockIndexReader(1, 1);
5658
assertNotNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
5759
assertNotNull(source.createSortedDocsProducerOrNull(reader, null));
60+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
5861
assertNull(source.createSortedDocsProducerOrNull(reader,
5962
new TermQuery(new Term("keyword", "toto)"))));
6063

@@ -112,6 +115,7 @@ public void testGlobalOrdinalsSorted() {
112115
IndexReader reader = mockIndexReader(1, 1);
113116
assertNotNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
114117
assertNotNull(source.createSortedDocsProducerOrNull(reader, null));
118+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
115119
assertNull(source.createSortedDocsProducerOrNull(reader,
116120
new TermQuery(new Term("keyword", "toto)"))));
117121

@@ -126,6 +130,7 @@ public void testGlobalOrdinalsSorted() {
126130
);
127131
assertNull(source.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
128132
assertNull(source.createSortedDocsProducerOrNull(reader, null));
133+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
129134

130135
source = new GlobalOrdinalValuesSource(
131136
BigArrays.NON_RECYCLING_INSTANCE,
@@ -137,6 +142,7 @@ public void testGlobalOrdinalsSorted() {
137142
-1
138143
);
139144
assertNull(source.createSortedDocsProducerOrNull(reader, null));
145+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
140146

141147
final MappedFieldType ip = new IpFieldMapper.IpFieldType();
142148
ip.setName("ip");
@@ -150,6 +156,7 @@ public void testGlobalOrdinalsSorted() {
150156
1
151157
);
152158
assertNull(source.createSortedDocsProducerOrNull(reader, null));
159+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("foo", "bar"))));
153160
}
154161

155162
public void testNumericSorted() {
@@ -179,6 +186,9 @@ public void testNumericSorted() {
179186
assertNotNull(source.createSortedDocsProducerOrNull(reader, LongPoint.newRangeQuery("number", 0, 1)));
180187
assertNotNull(source.createSortedDocsProducerOrNull(reader, new IndexOrDocValuesQuery(
181188
LongPoint.newRangeQuery("number", 0, 1), new MatchAllDocsQuery())));
189+
assertNotNull(source.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
190+
assertNotNull(source.createSortedDocsProducerOrNull(reader,
191+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
182192
assertNotNull(source.createSortedDocsProducerOrNull(reader, new BoostQuery(new IndexOrDocValuesQuery(
183193
LongPoint.newRangeQuery("number", 0, 1), new MatchAllDocsQuery()), 2.0f)));
184194
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
@@ -195,6 +205,9 @@ public void testNumericSorted() {
195205
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new MatchAllDocsQuery()));
196206
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, null));
197207
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
208+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
209+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader,
210+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
198211

199212
LongValuesSource sourceRev = new LongValuesSource(
200213
BigArrays.NON_RECYCLING_INSTANCE,
@@ -207,6 +220,10 @@ public void testNumericSorted() {
207220
-1
208221
);
209222
assertNull(sourceRev.createSortedDocsProducerOrNull(reader, null));
223+
assertNull(sourceRev.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
224+
assertNull(sourceRev.createSortedDocsProducerOrNull(reader,
225+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
226+
assertNull(sourceWithMissing.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
210227
} else if (numberType == NumberFieldMapper.NumberType.HALF_FLOAT ||
211228
numberType == NumberFieldMapper.NumberType.FLOAT ||
212229
numberType == NumberFieldMapper.NumberType.DOUBLE) {
@@ -221,6 +238,10 @@ public void testNumericSorted() {
221238
);
222239
IndexReader reader = mockIndexReader(1, 1);
223240
assertNull(source.createSortedDocsProducerOrNull(reader, null));
241+
assertNull(source.createSortedDocsProducerOrNull(reader, new DocValuesFieldExistsQuery("number")));
242+
assertNull(source.createSortedDocsProducerOrNull(reader, new TermQuery(new Term("keyword", "toto)"))));
243+
assertNull(source.createSortedDocsProducerOrNull(reader,
244+
new ConstantScoreQuery(new DocValuesFieldExistsQuery("number"))));
224245
} else{
225246
throw new AssertionError ("missing type:" + numberType.typeName());
226247
}

0 commit comments

Comments
 (0)