diff --git a/docs/changelog/94396.yaml b/docs/changelog/94396.yaml new file mode 100644 index 0000000000000..58cc074e895ab --- /dev/null +++ b/docs/changelog/94396.yaml @@ -0,0 +1,5 @@ +pr: 94396 +summary: Allow docvalues-only search on `geo_shape` +area: Geo +type: enhancement +issues: [] diff --git a/docs/reference/mapping/types/geo-shape.asciidoc b/docs/reference/mapping/types/geo-shape.asciidoc index 1d1da12ccf95f..37ef340733932 100644 --- a/docs/reference/mapping/types/geo-shape.asciidoc +++ b/docs/reference/mapping/types/geo-shape.asciidoc @@ -70,6 +70,14 @@ and reject the whole document. |`coerce` |If `true` unclosed linear rings in polygons will be automatically closed. | `false` +|`index` |Should the field be quickly searchable? Accepts `true` (default) and `false`. +Fields that only have <> enabled can still be queried, albeit slower. +| `true` + +|`doc_values` |Should the field be stored on disk in a column-stride fashion, +so that it can later be used for aggregations or scripting? +| `true` + |======================================================================= diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java index d7285823d6bb0..6a86eb0e6f5aa 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java @@ -197,6 +197,7 @@ public String typeName() { @Override public Query geoShapeQuery(SearchExecutionContext context, String fieldName, ShapeRelation relation, LatLonGeometry... geometries) { + failIfNotIndexedNorDocValuesFallback(context); // CONTAINS queries are not supported by VECTOR strategy for indices created before version 7.5.0 (Lucene 8.3.0) if (relation == ShapeRelation.CONTAINS && context.indexVersionCreated().before(Version.V_7_5_0)) { throw new QueryShardException( @@ -204,10 +205,15 @@ public Query geoShapeQuery(SearchExecutionContext context, String fieldName, Sha ShapeRelation.CONTAINS + " query relation not supported for Field [" + fieldName + "]." ); } - Query query = LatLonShape.newGeometryQuery(fieldName, relation.getLuceneRelation(), geometries); - if (hasDocValues()) { - final Query queryDocValues = new LatLonShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), geometries); - query = new IndexOrDocValuesQuery(query, queryDocValues); + Query query; + if (isIndexed()) { + query = LatLonShape.newGeometryQuery(fieldName, relation.getLuceneRelation(), geometries); + if (hasDocValues()) { + final Query queryDocValues = new LatLonShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), geometries); + query = new IndexOrDocValuesQuery(query, queryDocValues); + } + } else { + query = new LatLonShapeDocValuesQuery(fieldName, relation.getLuceneRelation(), geometries); } return query; } diff --git a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/ingest/CircleProcessorTests.java b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/ingest/CircleProcessorTests.java index 172cdeee2c83f..e9d12e99eaaf7 100644 --- a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/ingest/CircleProcessorTests.java +++ b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/ingest/CircleProcessorTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.search.Query; import org.apache.lucene.store.Directory; import org.apache.lucene.tests.index.RandomIndexWriter; +import org.elasticsearch.Version; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.geo.GeoJson; import org.elasticsearch.common.geo.Orientation; @@ -210,6 +211,7 @@ public void testGeoShapeQueryAcrossDateline() throws IOException { SearchExecutionContext mockedContext = mock(SearchExecutionContext.class); when(mockedContext.getFieldType(any())).thenReturn(shapeType); + when(mockedContext.indexVersionCreated()).thenReturn(Version.CURRENT); Query sameShapeQuery = shapeType.geoShapeQuery(mockedContext, fieldName, ShapeRelation.INTERSECTS, geometry); Query pointOnDatelineQuery = shapeType.geoShapeQuery( mockedContext, diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/110_geo_shape_parameters.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/110_geo_shape_parameters.yml new file mode 100644 index 0000000000000..6ebbe01c92bc2 --- /dev/null +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/110_geo_shape_parameters.yml @@ -0,0 +1,127 @@ +setup: + - do: + indices.create: + index: shapes + body: + mappings: + properties: + default: + type: geo_shape + no_doc_values: + type: geo_shape + doc_values: false + no_index: + type: geo_shape + index: false + no_doc_values_no_index: + type: geo_shape + doc_values: false + index: false + - do: + bulk: + refresh: true + body: + - index: + _index: shapes + _id: 1 + - '{"default": "POINT(4.912350 52.374081)", "no_doc_values": "POINT(4.912350 52.374081)", "no_index": "POINT(4.912350 52.374081)", "no_doc_values_no_index": "POINT(4.912350 52.374081)"}' + - index: + _index: shapes + _id: 2 + - '{"default": "POINT(2.327000 48.860000)", "no_doc_values": "POINT(2.327000 48.860000)", "no_index": "POINT(2.327000 48.860000)", "no_doc_values_no_index": "POINT(2.327000 48.860000)"}' + - do: + indices.refresh: {} + +--- +"Test field mapping": + - do: + indices.get_mapping: + index: shapes + + - match: {shapes.mappings.properties.default.type: geo_shape } + - match: {shapes.mappings.properties.no_doc_values.type: geo_shape } + - match: {shapes.mappings.properties.no_doc_values.doc_values: false } + - match: {shapes.mappings.properties.no_index.type: geo_shape } + - match: {shapes.mappings.properties.no_index.index: false } + - match: {shapes.mappings.properties.no_doc_values_no_index.type: geo_shape } + - match: {shapes.mappings.properties.no_doc_values_no_index.index: false } + - match: {shapes.mappings.properties.no_doc_values_no_index.doc_values: false } + +--- +"Test query default field": + - do: + search: + index: shapes + body: + query: + geo_bounding_box: + default: + top_left: + lat: 55 + lon: 4 + bottom_right: + lat: 50 + lon: 5 + + - match: { hits.total.value: 1 } + + +--- +"Test query no_doc_values field": + - do: + search: + index: shapes + body: + query: + geo_bounding_box: + no_doc_values: + top_left: + lat: 55 + lon: 4 + bottom_right: + lat: 50 + lon: 5 + + - match: { hits.total.value: 1 } + + +--- +"Test query no_index field": + - do: + search: + index: shapes + body: + query: + geo_bounding_box: + no_index: + top_left: + lat: 55 + lon: 4 + bottom_right: + lat: 50 + lon: 5 + + - match: { hits.total.value: 1 } + +--- +"Test query no_doc_values_no_index field": + - do: + catch: bad_request + search: + index: shapes + body: + query: + geo_bounding_box: + no_doc_values_no_index: + top_left: + lat: 55 + lon: 4 + bottom_right: + lat: 50 + lon: 5 + + - match: {error.type: search_phase_execution_exception} + - match: {error.reason: "all shards failed"} + - match: {error.phase: query} + - match: {error.failed_shards.0.reason.type: query_shard_exception} + - match: {error.failed_shards.0.reason.reason: "failed to create query: Cannot search on field [no_doc_values_no_index] since it is not indexed nor has doc values."}