Skip to content

Commit 8431c36

Browse files
authored
Support docvalues only query in shape field (#112199)
1 parent 48c32f1 commit 8431c36

File tree

5 files changed

+38
-49
lines changed

5 files changed

+38
-49
lines changed

docs/changelog/112199.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 112199
2+
summary: Support docvalues only query in shape field
3+
area: Geo
4+
type: enhancement
5+
issues: []

x-pack/plugin/spatial/src/internalClusterTest/java/org/elasticsearch/xpack/spatial/search/ShapeQueryOverShapeTests.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,18 @@ public class ShapeQueryOverShapeTests extends ShapeQueryTestCase {
5151

5252
@Override
5353
protected XContentBuilder createDefaultMapping() throws Exception {
54-
XContentBuilder xcb = XContentFactory.jsonBuilder()
54+
final boolean isIndexed = randomBoolean();
55+
final boolean hasDocValues = isIndexed == false || randomBoolean();
56+
return XContentFactory.jsonBuilder()
5557
.startObject()
5658
.startObject("properties")
5759
.startObject(defaultFieldName)
5860
.field("type", "shape")
61+
.field("index", isIndexed)
62+
.field("doc_values", hasDocValues)
5963
.endObject()
6064
.endObject()
6165
.endObject();
62-
63-
return xcb;
6466
}
6567

6668
@Override

x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.index.mapper.FieldMapper;
2727
import org.elasticsearch.index.mapper.MappedFieldType;
2828
import org.elasticsearch.index.mapper.MapperBuilderContext;
29+
import org.elasticsearch.index.query.QueryShardException;
2930
import org.elasticsearch.index.query.SearchExecutionContext;
3031
import org.elasticsearch.lucene.spatial.BinaryShapeDocValuesField;
3132
import org.elasticsearch.lucene.spatial.CartesianShapeIndexer;
@@ -162,7 +163,19 @@ public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext
162163

163164
@Override
164165
public Query shapeQuery(Geometry shape, String fieldName, ShapeRelation relation, SearchExecutionContext context) {
165-
return queryProcessor.shapeQuery(shape, fieldName, relation, context, hasDocValues());
166+
failIfNotIndexedNorDocValuesFallback(context);
167+
// CONTAINS queries are not supported by VECTOR strategy for indices created before version 7.5.0 (Lucene 8.3.0);
168+
if (relation == ShapeRelation.CONTAINS && context.indexVersionCreated().before(IndexVersions.V_7_5_0)) {
169+
throw new QueryShardException(
170+
context,
171+
ShapeRelation.CONTAINS + " query relation not supported for Field [" + fieldName + "]."
172+
);
173+
}
174+
try {
175+
return queryProcessor.shapeQuery(shape, fieldName, relation, isIndexed(), hasDocValues());
176+
} catch (IllegalArgumentException e) {
177+
throw new QueryShardException(context, "Exception creating query on Field [" + fieldName + "] " + e.getMessage(), e);
178+
}
166179
}
167180

168181
@Override

x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/query/ShapeQueryProcessor.java

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,51 +14,26 @@
1414
import org.elasticsearch.common.geo.LuceneGeometriesUtils;
1515
import org.elasticsearch.common.geo.ShapeRelation;
1616
import org.elasticsearch.geometry.Geometry;
17-
import org.elasticsearch.index.IndexVersions;
18-
import org.elasticsearch.index.mapper.MappedFieldType;
19-
import org.elasticsearch.index.query.QueryShardException;
20-
import org.elasticsearch.index.query.SearchExecutionContext;
2117
import org.elasticsearch.lucene.spatial.CartesianShapeDocValuesQuery;
22-
import org.elasticsearch.xpack.spatial.index.mapper.ShapeFieldMapper;
2318

2419
public class ShapeQueryProcessor {
2520

26-
public Query shapeQuery(
27-
Geometry geometry,
28-
String fieldName,
29-
ShapeRelation relation,
30-
SearchExecutionContext context,
31-
boolean hasDocValues
32-
) {
33-
validateIsShapeFieldType(fieldName, context);
34-
// CONTAINS queries are not supported by VECTOR strategy for indices created before version 7.5.0 (Lucene 8.3.0);
35-
if (relation == ShapeRelation.CONTAINS && context.indexVersionCreated().before(IndexVersions.V_7_5_0)) {
36-
throw new QueryShardException(context, ShapeRelation.CONTAINS + " query relation not supported for Field [" + fieldName + "].");
37-
}
21+
public Query shapeQuery(Geometry geometry, String fieldName, ShapeRelation relation, boolean indexed, boolean hasDocValues) {
22+
assert indexed || hasDocValues;
3823
if (geometry == null || geometry.isEmpty()) {
3924
return new MatchNoDocsQuery();
4025
}
41-
final XYGeometry[] luceneGeometries;
42-
try {
43-
luceneGeometries = LuceneGeometriesUtils.toXYGeometry(geometry, t -> {});
44-
} catch (IllegalArgumentException e) {
45-
throw new QueryShardException(context, "Exception creating query on Field [" + fieldName + "] " + e.getMessage(), e);
46-
}
47-
Query query = XYShape.newGeometryQuery(fieldName, relation.getLuceneRelation(), luceneGeometries);
48-
if (hasDocValues) {
49-
final Query queryDocValues = new CartesianShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), luceneGeometries);
50-
query = new IndexOrDocValuesQuery(query, queryDocValues);
26+
final XYGeometry[] luceneGeometries = LuceneGeometriesUtils.toXYGeometry(geometry, t -> {});
27+
Query query;
28+
if (indexed) {
29+
query = XYShape.newGeometryQuery(fieldName, relation.getLuceneRelation(), luceneGeometries);
30+
if (hasDocValues) {
31+
final Query queryDocValues = new CartesianShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), luceneGeometries);
32+
query = new IndexOrDocValuesQuery(query, queryDocValues);
33+
}
34+
} else {
35+
query = new CartesianShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), luceneGeometries);
5136
}
5237
return query;
5338
}
54-
55-
private void validateIsShapeFieldType(String fieldName, SearchExecutionContext context) {
56-
MappedFieldType fieldType = context.getFieldType(fieldName);
57-
if (fieldType instanceof ShapeFieldMapper.ShapeFieldType == false) {
58-
throw new QueryShardException(
59-
context,
60-
"Expected " + ShapeFieldMapper.CONTENT_TYPE + " field type for Field [" + fieldName + "] but found " + fieldType.typeName()
61-
);
62-
}
63-
}
6439
}

x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/ingest/CircleProcessorTests.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.elasticsearch.geometry.utils.WellKnownText;
2828
import org.elasticsearch.index.IndexVersion;
2929
import org.elasticsearch.index.mapper.GeoShapeIndexer;
30-
import org.elasticsearch.index.mapper.MappedFieldType;
3130
import org.elasticsearch.index.query.SearchExecutionContext;
3231
import org.elasticsearch.ingest.IngestDocument;
3332
import org.elasticsearch.ingest.RandomDocumentPicks;
@@ -39,7 +38,6 @@
3938
import org.elasticsearch.xcontent.XContentFactory;
4039
import org.elasticsearch.xcontent.XContentType;
4140
import org.elasticsearch.xpack.spatial.index.mapper.GeoShapeWithDocValuesFieldMapper.GeoShapeWithDocValuesFieldType;
42-
import org.elasticsearch.xpack.spatial.index.mapper.ShapeFieldMapper.ShapeFieldType;
4341
import org.elasticsearch.xpack.spatial.index.query.ShapeQueryProcessor;
4442

4543
import java.io.IOException;
@@ -244,17 +242,13 @@ public void testShapeQuery() throws IOException {
244242
int numSides = randomIntBetween(4, 1000);
245243
Geometry geometry = CircleUtils.createRegularShapePolygon(circle, numSides);
246244

247-
MappedFieldType shapeType = new ShapeFieldType(fieldName, true, true, Orientation.RIGHT, null, Collections.emptyMap());
248-
249245
ShapeQueryProcessor processor = new ShapeQueryProcessor();
250-
SearchExecutionContext mockedContext = mock(SearchExecutionContext.class);
251-
when(mockedContext.getFieldType(any())).thenReturn(shapeType);
252-
Query sameShapeQuery = processor.shapeQuery(geometry, fieldName, ShapeRelation.INTERSECTS, mockedContext, true);
246+
Query sameShapeQuery = processor.shapeQuery(geometry, fieldName, ShapeRelation.INTERSECTS, true, true);
253247
Query centerPointQuery = processor.shapeQuery(
254248
new Point(circle.getLon(), circle.getLat()),
255249
fieldName,
256250
ShapeRelation.INTERSECTS,
257-
mockedContext,
251+
true,
258252
true
259253
);
260254

0 commit comments

Comments
 (0)