diff --git a/docs/reference/mapping/types/geo-shape.asciidoc b/docs/reference/mapping/types/geo-shape.asciidoc index 6f829b802f167..caea17a6121a6 100644 --- a/docs/reference/mapping/types/geo-shape.asciidoc +++ b/docs/reference/mapping/types/geo-shape.asciidoc @@ -79,7 +79,7 @@ greater false positives. Note: This parameter is only relevant for `term` and `recursive` strategies. | `0.025` -|`orientation` +|`orientation` a|Optional. Vertex order for the shape's coordinates list. This parameter sets and returns only a `RIGHT` (counterclockwise) or `LEFT` @@ -649,43 +649,6 @@ IMPORTANT: You cannot index the `circle` type using the default <> to approximate the circle as a <>. -The `circle` type requires a `geo_shape` field mapping with the deprecated -`recursive` Prefix Tree strategy. - -[source,console] ----- -PUT /circle-example -{ - "mappings": { - "properties": { - "location": { - "type": "geo_shape", - "strategy": "recursive" - } - } - } -} ----- -// TEST[warning:Parameter [strategy] is deprecated and will be removed in a future version] - -The following request indexes a `circle` geo-shape. - -[source,console] ----- -POST /circle-example/_doc -{ - "location" : { - "type" : "circle", - "coordinates" : [101.0, 1.0], - "radius" : "100m" - } -} ----- -// TEST[continued] - -Note: The inner `radius` field is required. If not specified, then -the units of the `radius` will default to `METERS`. - *NOTE:* Neither GeoJSON or WKT support a point-radius circle type. [discrete] diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java index 7572e4e3d90cc..f1c76403f9e4c 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java @@ -200,8 +200,9 @@ public void testShapeRelations() throws Exception { .endObject() .endObject()); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("shapes") - .setMapping(mapping); + .setMapping(mapping).setSettings(settings(version).build()); mappingRequest.get(); client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().get(); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java index f0248b0580d5e..24efe991e11d8 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java @@ -7,6 +7,7 @@ */ package org.elasticsearch.search.geo; +import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.cluster.ClusterState; @@ -22,6 +23,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.VersionUtils; import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -32,14 +34,19 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase { + @Override + protected boolean forbidPrivateIndexSettings() { + return false; + } + @Override protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) { return Settings.builder() - // Check that only geo-shape queries on legacy PrefixTree based - // geo shapes are disallowed. - .put("search.allow_expensive_queries", false) - .put(super.nodeSettings(nodeOrdinal, otherSettings)) - .build(); + // Check that only geo-shape queries on legacy PrefixTree based + // geo shapes are disallowed. + .put("search.allow_expensive_queries", false) + .put(super.nodeSettings(nodeOrdinal, otherSettings)) + .build(); } /** @@ -125,17 +132,17 @@ public void testIgnoreMalformed() throws Exception { assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); } - public void testMappingUpdate() throws Exception { + public void testMappingUpdate() { // create index - assertAcked(client().admin().indices().prepareCreate("test") - .setMapping("shape", "type=geo_shape").get()); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + assertAcked(client().admin().indices().prepareCreate("test").setSettings(settings(version).build()) + .setMapping("shape", "type=geo_shape,strategy=recursive").get()); ensureGreen(); String update ="{\n" + " \"properties\": {\n" + " \"shape\": {\n" + - " \"type\": \"geo_shape\",\n" + - " \"strategy\": \"recursive\"\n" + + " \"type\": \"geo_shape\"" + " }\n" + " }\n" + "}"; @@ -143,7 +150,7 @@ public void testMappingUpdate() throws Exception { IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> client().admin().indices() .preparePutMapping("test") .setSource(update, XContentType.JSON).get()); - assertThat(e.getMessage(), containsString("mapper [shape] of type [geo_shape] cannot change strategy from [BKD] to [recursive]")); + assertThat(e.getMessage(), containsString("mapper [shape] of type [geo_shape] cannot change strategy from [recursive] to [BKD]")); } /** @@ -184,33 +191,35 @@ public void testIndexShapeRouting() throws Exception { public void testIndexPolygonDateLine() throws Exception { String mappingVector = "{\n" + - " \"properties\": {\n" + - " \"shape\": {\n" + - " \"type\": \"geo_shape\"\n" + - " }\n" + - " }\n" + - " }"; + " \"properties\": {\n" + + " \"shape\": {\n" + + " \"type\": \"geo_shape\"\n" + + " }\n" + + " }\n" + + " }"; String mappingQuad = "{\n" + - " \"properties\": {\n" + - " \"shape\": {\n" + - " \"type\": \"geo_shape\",\n" + - " \"tree\": \"quadtree\"\n" + - " }\n" + - " }\n" + - " }"; + " \"properties\": {\n" + + " \"shape\": {\n" + + " \"type\": \"geo_shape\",\n" + + " \"tree\": \"quadtree\"\n" + + " }\n" + + " }\n" + + " }"; // create index assertAcked(client().admin().indices().prepareCreate("vector").setMapping(mappingVector).get()); ensureGreen(); - assertAcked(client().admin().indices().prepareCreate("quad").setMapping(mappingQuad).get()); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + assertAcked(client().admin().indices().prepareCreate("quad") + .setSettings(settings(version).build()).setMapping(mappingQuad).get()); ensureGreen(); String source = "{\n" + - " \"shape\" : \"POLYGON((179 0, -179 0, -179 2, 179 2, 179 0))\""+ - "}"; + " \"shape\" : \"POLYGON((179 0, -179 0, -179 2, 179 2, 179 0))\""+ + "}"; indexRandom(true, client().prepareIndex("quad").setId("0").setSource(source, XContentType.JSON)); indexRandom(true, client().prepareIndex("vector").setId("0").setSource(source, XContentType.JSON)); @@ -221,25 +230,25 @@ public void testIndexPolygonDateLine() throws Exception { assertAcked(client().admin().cluster().updateSettings(updateSettingsRequest).actionGet()); SearchResponse searchResponse = client().prepareSearch("quad").setQuery( - geoShapeQuery("shape", new PointBuilder(-179.75, 1)) + geoShapeQuery("shape", new PointBuilder(-179.75, 1)) ).get(); assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); searchResponse = client().prepareSearch("quad").setQuery( - geoShapeQuery("shape", new PointBuilder(90, 1)) + geoShapeQuery("shape", new PointBuilder(90, 1)) ).get(); assertThat(searchResponse.getHits().getTotalHits().value, equalTo(0L)); searchResponse = client().prepareSearch("quad").setQuery( - geoShapeQuery("shape", new PointBuilder(-180, 1)) + geoShapeQuery("shape", new PointBuilder(-180, 1)) ).get(); assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); searchResponse = client().prepareSearch("quad").setQuery( - geoShapeQuery("shape", new PointBuilder(180, 1)) + geoShapeQuery("shape", new PointBuilder(180, 1)) ).get(); assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L)); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java index 6acaa03349c9b..d0a9d7670ad72 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java @@ -8,6 +8,7 @@ package org.elasticsearch.search.geo; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.cluster.ClusterState; @@ -24,6 +25,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.VersionUtils; import java.io.IOException; @@ -35,10 +37,16 @@ public class LegacyGeoShapeIntegrationIT extends ESIntegTestCase { + @Override + protected boolean forbidPrivateIndexSettings() { + return false; + } + /** * Test that orientation parameter correctly persists across cluster restart */ public void testOrientationPersistence() throws Exception { + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); String idxName = "orientation"; String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("location") @@ -49,7 +57,7 @@ public void testOrientationPersistence() throws Exception { .endObject().endObject()); // create index - assertAcked(prepareCreate(idxName).setMapping(mapping)); + assertAcked(prepareCreate(idxName).setMapping(mapping).setSettings(settings(version).build())); mapping = Strings.toString(XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("location") @@ -59,7 +67,7 @@ public void testOrientationPersistence() throws Exception { .endObject() .endObject().endObject()); - assertAcked(prepareCreate(idxName+"2").setMapping(mapping)); + assertAcked(prepareCreate(idxName+"2").setMapping(mapping).setSettings(settings(version).build())); ensureGreen(idxName, idxName+"2"); internalCluster().fullRestart(); @@ -95,7 +103,8 @@ public void testOrientationPersistence() throws Exception { */ public void testIgnoreMalformed() throws Exception { // create index - assertAcked(client().admin().indices().prepareCreate("test") + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + assertAcked(prepareCreate("test").setSettings(settings(version).build()) .setMapping("shape", "type=geo_shape,tree=quadtree,ignore_malformed=true").get()); ensureGreen(); @@ -136,9 +145,9 @@ public void testIndexShapeRouting() throws Exception { " }\n" + " }}"; - + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); // create index - assertAcked(client().admin().indices().prepareCreate("test").setMapping(mapping).get()); + assertAcked(prepareCreate("test").setSettings(settings(version).build()).setMapping(mapping).get()); ensureGreen(); String source = "{\n" + @@ -162,7 +171,8 @@ public void testIndexShapeRouting() throws Exception { */ public void testLegacyCircle() throws Exception { // create index - assertAcked(client().admin().indices().prepareCreate("test") + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + assertAcked(prepareCreate("test").setSettings(settings(version).build()) .setMapping("shape", "type=geo_shape,strategy=recursive,tree=geohash").get()); ensureGreen(); @@ -181,9 +191,10 @@ public void testLegacyCircle() throws Exception { } public void testDisallowExpensiveQueries() throws InterruptedException, IOException { + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); try { // create index - assertAcked(client().admin().indices().prepareCreate("test") + assertAcked(client().admin().indices().prepareCreate("test").setSettings(settings(version).build()) .setMapping("shape", "type=geo_shape,strategy=recursive,tree=geohash").get()); ensureGreen(); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index faadc06d102a5..9817ce0497f8f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; /** * FieldMapper for indexing {@link LatLonShape}s. @@ -144,6 +145,11 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat boolean ignoreMalformedByDefault = IGNORE_MALFORMED_SETTING.get(parserContext.getSettings()); boolean coerceByDefault = COERCE_SETTING.get(parserContext.getSettings()); if (LegacyGeoShapeFieldMapper.containsDeprecatedParameter(node.keySet())) { + if (parserContext.indexVersionCreated().onOrAfter(Version.V_8_0_0)) { + Set deprecatedParams = LegacyGeoShapeFieldMapper.getDeprecatedParameters(node.keySet()); + throw new IllegalArgumentException("using deprecated parameters " + Arrays.toString(deprecatedParams.toArray()) + + " in mapper [" + name + "] of type [geo_shape] is no longer allowed"); + } builder = new LegacyGeoShapeFieldMapper.Builder( name, parserContext.indexVersionCreated(), diff --git a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java index 0d7bfc68d861d..0ff9b009f1ec0 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java @@ -47,6 +47,7 @@ import java.util.Objects; import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * FieldMapper for indexing {@link org.locationtech.spatial4j.shape.Shape}s. @@ -82,6 +83,10 @@ public static boolean containsDeprecatedParameter(Set paramKeys) { return DEPRECATED_PARAMETERS.stream().anyMatch(paramKeys::contains); } + public static Set getDeprecatedParameters(Set paramKeys) { + return DEPRECATED_PARAMETERS.stream().filter((p) -> paramKeys.contains(p)).collect(Collectors.toSet()); + } + public static class Defaults { public static final SpatialStrategy STRATEGY = SpatialStrategy.RECURSIVE; public static final String TREE = "quadtree"; diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java index 5db1b0c501717..999fd006f4382 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java @@ -291,8 +291,10 @@ public void testParse3DPolygon() throws IOException, ParseException { LinearRing shell = GEOMETRY_FACTORY.createLinearRing(shellCoordinates.toArray(new Coordinate[shellCoordinates.size()])); Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, null); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); final LegacyGeoShapeFieldMapper mapperBuilder = - new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true).build(new ContentPath()); + new LegacyGeoShapeFieldMapper.Builder("test", version, false, true) + .build(new ContentPath()); try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); ElasticsearchGeoAssertions.assertEquals(jtsGeom(expected), ShapeParser.parse(parser, mapperBuilder).buildS4J()); diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java index e2b0b6bcde7a6..acea22651bd3c 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java @@ -35,6 +35,7 @@ import org.elasticsearch.index.mapper.GeoShapeFieldMapper; import org.elasticsearch.index.mapper.GeoShapeIndexer; import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper; +import org.elasticsearch.test.VersionUtils; import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.LineString; @@ -325,8 +326,10 @@ public void testParseMixedDimensionPolyWithHoleStoredZ() throws IOException { XContentParser parser = createParser(xContentBuilder); parser.nextToken(); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); final LegacyGeoShapeFieldMapper mapperBuilder = - new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true).build(new ContentPath()); + new LegacyGeoShapeFieldMapper.Builder("test", version, false, true) + .build(new ContentPath()); // test store z disabled ElasticsearchException e = expectThrows(ElasticsearchException.class, @@ -348,8 +351,10 @@ public void testParsePolyWithStoredZ() throws IOException { XContentParser parser = createParser(xContentBuilder); parser.nextToken(); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); final LegacyGeoShapeFieldMapper mapperBuilder = - new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true).build(new ContentPath()); + new LegacyGeoShapeFieldMapper.Builder("test", version, false, true) + .build(new ContentPath()); ShapeBuilder shapeBuilder = ShapeParser.parse(parser, mapperBuilder); assertEquals(shapeBuilder.numDimensions(), 3); @@ -362,14 +367,17 @@ public void testParseOpenPolygon() throws IOException { XContentParser parser = createParser(xContentBuilder); parser.nextToken(); + final Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); final LegacyGeoShapeFieldMapper defaultMapperBuilder = - new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true).coerce(false).build(new ContentPath()); + new LegacyGeoShapeFieldMapper.Builder("test", version, false, true) + .coerce(false).build(new ContentPath()); ElasticsearchParseException exception = expectThrows(ElasticsearchParseException.class, () -> ShapeParser.parse(parser, defaultMapperBuilder)); assertEquals("invalid LinearRing found (coordinates are not closed)", exception.getMessage()); final LegacyGeoShapeFieldMapper coercingMapperBuilder = - new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true).coerce(true).build(new ContentPath()); + new LegacyGeoShapeFieldMapper.Builder("test", Version.CURRENT, false, true) + .coerce(true).build(new ContentPath()); ShapeBuilder shapeBuilder = ShapeParser.parse(parser, coercingMapperBuilder); assertNotNull(shapeBuilder); assertEquals("polygon ((100.0 5.0, 100.0 10.0, 90.0 10.0, 90.0 5.0, 100.0 5.0))", shapeBuilder.toWKT()); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java b/server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java index 9863ad0f3dd6e..0156087d053f3 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java @@ -297,9 +297,7 @@ public Function> getFieldFilter() { " \"type\": \"geo_point\"\n" + " },\n" + " \"area_visible\": {\n" + - " \"type\": \"geo_shape\", \n" + - " \"tree\": \"quadtree\",\n" + - " \"precision\": \"1m\"\n" + + " \"type\": \"geo_shape\"" + " }\n" + " }\n" + " },\n" + diff --git a/server/src/test/java/org/elasticsearch/index/mapper/GeoShapeFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/GeoShapeFieldMapperTests.java index 86e112f93d8f1..7010f57f1ce9c 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/GeoShapeFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/GeoShapeFieldMapperTests.java @@ -7,12 +7,14 @@ */ package org.elasticsearch.index.mapper; +import org.elasticsearch.Version; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin; +import org.elasticsearch.test.VersionUtils; import java.io.IOException; import java.util.Collection; @@ -181,7 +183,8 @@ public void testGeoShapeMapperMerge() throws Exception { } public void testGeoShapeLegacyMerge() throws Exception { - MapperService m = createMapperService(fieldMapping(b -> b.field("type", "geo_shape"))); + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + MapperService m = createMapperService(version, fieldMapping(b -> b.field("type", "geo_shape"))); Exception e = expectThrows(IllegalArgumentException.class, () -> merge(m, fieldMapping(b -> b.field("type", "geo_shape").field("strategy", "recursive")))); @@ -189,7 +192,7 @@ public void testGeoShapeLegacyMerge() throws Exception { containsString("mapper [field] of type [geo_shape] cannot change strategy from [BKD] to [recursive]")); assertFieldWarnings("strategy"); - MapperService lm = createMapperService(fieldMapping(b -> b.field("type", "geo_shape").field("strategy", "recursive"))); + MapperService lm = createMapperService(version, fieldMapping(b -> b.field("type", "geo_shape").field("strategy", "recursive"))); e = expectThrows(IllegalArgumentException.class, () -> merge(lm, fieldMapping(b -> b.field("type", "geo_shape")))); assertThat(e.getMessage(), diff --git a/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java index 31cbb64ceed76..efaf4e4235139 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.Version; import org.elasticsearch.common.CheckedConsumer; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.GeoUtils; @@ -25,6 +26,7 @@ import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin; +import org.elasticsearch.test.VersionUtils; import java.io.IOException; import java.util.Collection; @@ -103,6 +105,29 @@ protected boolean supportsMeta() { return false; } + @Override + protected MapperService createMapperService(XContentBuilder mappings) throws IOException { + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + return createMapperService(version, mappings); + } + + @Override + protected MapperService createMapperService(Version version, XContentBuilder mapping) throws IOException { + assumeFalse("LegacyGeoShapeFieldMapper can't be created in version " + version, version.onOrAfter(Version.V_8_0_0)); + return super.createMapperService(version, mapping); + } + + public void testInvalidCurrentVersion() { + MapperParsingException e = + expectThrows(MapperParsingException.class, + () -> super.createMapperService(Version.CURRENT, fieldMapping((b) -> { + b.field("type", "geo_shape").field("strategy", "recursive"); + }))); + assertThat(e.getMessage(), + containsString("using deprecated parameters [strategy] " + + "in mapper [field] of type [geo_shape] is no longer allowed")); + } + public void testLegacySwitches() throws IOException { // if one of the legacy parameters is added to a 'type':'geo_shape' config then // that will select the legacy field mapper diff --git a/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java b/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java index 11159e27a3dfd..cc4326e4e4fe6 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.Version; import org.elasticsearch.common.geo.SpatialStrategy; import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper.GeoShapeFieldType; +import org.elasticsearch.test.VersionUtils; import java.io.IOException; import java.util.List; @@ -31,8 +32,8 @@ public void testSetStrategyName() { } public void testFetchSourceValue() throws IOException { - - MappedFieldType mapper = new LegacyGeoShapeFieldMapper.Builder("field", Version.CURRENT, false, true) + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + MappedFieldType mapper = new LegacyGeoShapeFieldMapper.Builder("field", version, false, true) .build(new ContentPath()).fieldType(); Map jsonLineString = Map.of("type", "LineString", "coordinates", diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index fd3b17819a929..6416124b06acb 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -10,6 +10,7 @@ import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.Version; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.CheckedSupplier; @@ -35,6 +36,7 @@ import org.elasticsearch.index.query.ExistsQueryBuilder; import org.elasticsearch.index.query.GeoShapeQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.test.VersionUtils; import org.elasticsearch.test.geo.RandomShapeGenerator; import org.locationtech.jts.geom.Coordinate; import org.locationtech.spatial4j.shape.Rectangle; @@ -73,6 +75,11 @@ protected XContentBuilder createDefaultMapping() throws Exception { return xcb; } + @Override + protected boolean forbidPrivateIndexSettings() { + return false; + } + protected XContentBuilder createPrefixTreeMapping(String tree) throws Exception { XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() .startObject("properties").startObject("geo") @@ -85,16 +92,23 @@ protected XContentBuilder createPrefixTreeMapping(String tree) throws Exception return xcb; } - protected XContentBuilder createRandomMapping() throws Exception { - XContentBuilder xcb = XContentFactory.jsonBuilder().startObject() - .startObject("properties").startObject("geo") - .field("type", "geo_shape"); - if (randomBoolean()) { - xcb = xcb.field("tree", randomFrom(PREFIX_TREES)); + protected void createRandomMapping(String indexName, Settings settings) throws Exception { + boolean legacy = randomBoolean(); + final XContentBuilder mapping = legacy ? createPrefixTreeMapping(randomFrom(PREFIX_TREES)) : createDefaultMapping(); + final Settings finalSetting; + if (legacy) { + MapperParsingException ex = + expectThrows(MapperParsingException.class, + () -> client().admin().indices().prepareCreate(indexName).setMapping(mapping).setSettings(settings).get()); + assertThat(ex.getMessage(), + containsString("using deprecated parameters [tree] in mapper [geo] of type [geo_shape] is no longer allowed")); + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + finalSetting = settings(version).put(settings).build(); + } else { + finalSetting = settings; } - xcb = xcb.endObject().endObject().endObject(); - - return xcb; + client().admin().indices().prepareCreate(indexName).setMapping(mapping).setSettings(finalSetting).get(); + ensureGreen(); } public void testShapeFetchingPath() throws Exception { @@ -182,7 +196,6 @@ public void testShapeFetchingPath() throws Exception { public void testRandomGeoCollectionQuery() throws Exception { // Create a random geometry collection to index. GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random());; - org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); assumeTrue("Skipping the check for the polygon with a degenerated dimension", @@ -196,10 +209,7 @@ public void testRandomGeoCollectionQuery() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - XContentBuilder mapping = createRandomMapping(); - Settings settings = Settings.builder().put("index.number_of_shards", 1).build(); - client().admin().indices().prepareCreate("test").setMapping(mapping).setSettings(settings).get(); - ensureGreen(); + createRandomMapping("test", Settings.builder().put("index.number_of_shards", 1).build()); XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); @@ -384,8 +394,7 @@ public void testEdgeCases() throws Exception { } public void testIndexedShapeReferenceSourceDisabled() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + createRandomMapping("test", Settings.builder().put("index.number_of_shards", 1).build()); createIndex("shapes", Settings.EMPTY, "shape_type", "_source", "enabled=false"); ensureGreen(); @@ -427,9 +436,7 @@ public void testPointQuery() throws Exception { gcb.shape(pb); // create mapping - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test", Settings.EMPTY); XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); @@ -466,7 +473,18 @@ public void testContainsShapeQuery() throws Exception { usePrefixTrees ? createPrefixTreeMapping(LegacyGeoShapeFieldMapper.PrefixTrees.QUADTREE) : createDefaultMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + + if (usePrefixTrees) { + MapperParsingException ex = + expectThrows(MapperParsingException.class, + () -> client().admin().indices().prepareCreate("test").setMapping(mapping).get()); + assertThat(ex.getMessage(), + containsString("using deprecated parameters [tree] in mapper [geo] of type [geo_shape] is no longer allowed")); + } + + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + Settings settings = usePrefixTrees ? settings(version).build() : Settings.EMPTY; + client().admin().indices().prepareCreate("test").setMapping(mapping).setSettings(settings).get(); ensureGreen(); XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); @@ -493,10 +511,7 @@ public void testExistsQuery() throws Exception { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - String mapping = Strings.toString(createRandomMapping()); - - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test", Settings.EMPTY); XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); @@ -518,7 +533,16 @@ public void testPointsOnly() throws Exception { .endObject() .endObject().endObject()); - client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).get(); + MapperParsingException ex = + expectThrows(MapperParsingException.class, + () -> client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).get()); + assertThat(ex.getMessage(), + containsString("using deprecated parameters [points_only, tree, distance_error_pct, tree_levels] " + + "in mapper [geo] of type [geo_shape] is no longer allowed")); + + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + Settings settings = settings(version).build(); + client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).setSettings(settings).get(); ensureGreen(); ShapeBuilder shape = RandomShapeGenerator.createShape(random()); @@ -551,7 +575,16 @@ public void testPointsOnlyExplicit() throws Exception { .endObject() .endObject().endObject()); - client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).get(); + MapperParsingException ex = + expectThrows(MapperParsingException.class, + () -> client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).get()); + assertThat(ex.getMessage(), + containsString("using deprecated parameters [points_only, tree, distance_error_pct, tree_levels] " + + "in mapper [geo] of type [geo_shape] is no longer allowed")); + + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + Settings settings = settings(version).build(); + client().admin().indices().prepareCreate("geo_points_only").setMapping(mapping).setSettings(settings).get(); ensureGreen(); // MULTIPOINT @@ -575,10 +608,8 @@ public void testPointsOnlyExplicit() throws Exception { } public void testIndexedShapeReference() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - createIndex("shapes"); - ensureGreen(); + + createRandomMapping("test", Settings.EMPTY); EnvelopeBuilder shape = new EnvelopeBuilder(new Coordinate(-45, 45), new Coordinate(45, -45)); @@ -625,7 +656,17 @@ public void testFieldAlias() throws IOException { .endObject() .endObject() .endObject()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + + + MapperParsingException ex = + expectThrows(MapperParsingException.class, + () -> client().admin().indices().prepareCreate("test").setMapping(mapping).get()); + assertThat(ex.getMessage(), + containsString("using deprecated parameters [tree] in mapper [geo] of type [geo_shape] is no longer allowed")); + + Version version = VersionUtils.randomPreviousCompatibleVersion(random(), Version.V_8_0_0); + Settings settings = settings(version).build(); + client().admin().indices().prepareCreate("test").setMapping(mapping).setSettings(settings).get(); ensureGreen(); ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT); @@ -641,7 +682,6 @@ public void testFieldAlias() throws IOException { public void testQueryRandomGeoCollection() throws Exception { // Create a random geometry collection. - String mapping = Strings.toString(createRandomMapping()); GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); org.apache.lucene.geo.Polygon randomPoly = GeoTestUtil.nextPolygon(); CoordinatesBuilder cb = new CoordinatesBuilder(); @@ -652,8 +692,7 @@ public void testQueryRandomGeoCollection() throws Exception { logger.info("Created Random GeometryCollection containing {} shapes", gcb.numShapes()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test", Settings.EMPTY); XContentBuilder docSource = gcb.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); @@ -671,9 +710,7 @@ public void testQueryRandomGeoCollection() throws Exception { } public void testShapeFilterWithDefinedGeoCollection() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test", Settings.EMPTY); XContentBuilder docSource = jsonBuilder().startObject().startObject("geo") .field("type", "geometrycollection") @@ -741,9 +778,7 @@ public void testShapeFilterWithDefinedGeoCollection() throws Exception { } public void testDistanceQuery() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - client().admin().indices().prepareCreate("test_distance").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test_distance", Settings.EMPTY); CircleBuilder circleBuilder = new CircleBuilder().center(new Coordinate(1, 0)).radius(350, DistanceUnit.KILOMETERS); @@ -779,10 +814,7 @@ public void testDistanceQuery() throws Exception { } public void testIndexRectangleSpanningDateLine() throws Exception { - String mapping = Strings.toString(createRandomMapping()); - - client().admin().indices().prepareCreate("test").setMapping(mapping).get(); - ensureGreen(); + createRandomMapping("test", Settings.EMPTY); EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(178, 10), new Coordinate(-178, -10)); diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java index 40f8da8076470..0a331cc3239a2 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java @@ -152,7 +152,7 @@ protected final MapperService createMapperService(Settings settings, String mapp return mapperService; } - protected final MapperService createMapperService(Version version, XContentBuilder mapping) throws IOException { + protected MapperService createMapperService(Version version, XContentBuilder mapping) throws IOException { return createMapperService(version, getIndexSettings(), () -> true, mapping); } 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 71065a458b62c..0a670cb54437e 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 @@ -44,6 +44,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Supplier; /** @@ -176,6 +177,11 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat boolean ignoreMalformedByDefault = IGNORE_MALFORMED_SETTING.get(parserContext.getSettings()); boolean coerceByDefault = COERCE_SETTING.get(parserContext.getSettings()); if (LegacyGeoShapeFieldMapper.containsDeprecatedParameter(node.keySet())) { + if (parserContext.indexVersionCreated().onOrAfter(Version.V_8_0_0)) { + Set deprecatedParams = LegacyGeoShapeFieldMapper.getDeprecatedParameters(node.keySet()); + throw new IllegalArgumentException("using deprecated parameters " + Arrays.toString(deprecatedParams.toArray()) + + " in mapper [" + name + "] of type [geo_shape] is no longer allowed"); + } builder = new LegacyGeoShapeFieldMapper.Builder( name, parserContext.indexVersionCreated(), diff --git a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java index 3a37124f5e0a5..251112fb4c0ed 100644 --- a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java +++ b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; +import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperTestCase; import org.elasticsearch.index.mapper.ParsedDocument; @@ -38,6 +39,7 @@ import java.util.Collection; import java.util.Collections; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; @@ -270,6 +272,17 @@ public void testGeoShapeMapperMerge() throws Exception { assertThat(geoShapeFieldMapper.fieldType().orientation(), equalTo(ShapeBuilder.Orientation.CW)); } + public void testInvalidCurrentVersion() { + MapperParsingException e = + expectThrows(MapperParsingException.class, + () -> super.createMapperService(Version.CURRENT, fieldMapping((b) -> { + b.field("type", "geo_shape").field("strategy", "recursive"); + }))); + assertThat(e.getMessage(), + containsString("using deprecated parameters [strategy] " + + "in mapper [field] of type [geo_shape] is no longer allowed")); + } + public void testSerializeDefaults() throws Exception { DocumentMapper defaultMapper = createDocumentMapper(fieldMapping(this::minimalMapping)); String serialized = toXContentString((GeoShapeWithDocValuesFieldMapper) defaultMapper.mappers().getMapper("field"));