Browse Source

Disallow creating geo_shape mappings with deprecated parameters (#70850)

With the introduction of BKD-based geo shape indexing in #32039, the prefix tree indexing method has 
been deprecated. From 8.0.0, it will not be allowed to create new mappings using deprecated parameters.
Ignacio Vera 4 years ago
parent
commit
4fff3788f3
16 changed files with 217 additions and 134 deletions
  1. 1 38
      docs/reference/mapping/types/geo-shape.asciidoc
  2. 2 1
      server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java
  3. 40 31
      server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java
  4. 18 7
      server/src/internalClusterTest/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java
  5. 6 0
      server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java
  6. 5 0
      server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java
  7. 3 1
      server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java
  8. 12 4
      server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java
  9. 1 3
      server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java
  10. 5 2
      server/src/test/java/org/elasticsearch/index/mapper/GeoShapeFieldMapperTests.java
  11. 25 0
      server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java
  12. 3 2
      server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java
  13. 76 44
      server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java
  14. 1 1
      test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java
  15. 6 0
      x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java
  16. 13 0
      x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java

+ 1 - 38
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
 <<ingest-circle-processor,circle ingest processor>> to approximate the circle as
 a <<geo-polygon,`polygon`>>.
 
-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]

+ 2 - 1
server/src/internalClusterTest/java/org/elasticsearch/search/geo/GeoFilterIT.java

@@ -200,8 +200,9 @@ public class GeoFilterIT extends ESIntegTestCase {
                 .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();
 

+ 40 - 31
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.GeoShapeFieldMapper;
 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 @@ import static org.hamcrest.Matchers.instanceOf;
 
 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 class GeoShapeIntegrationIT extends ESIntegTestCase {
         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 class GeoShapeIntegrationIT extends ESIntegTestCase {
         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 class GeoShapeIntegrationIT extends ESIntegTestCase {
 
     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 class GeoShapeIntegrationIT extends ESIntegTestCase {
             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));

+ 18 - 7
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.LegacyGeoShapeFieldMapper;
 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 @@ import static org.hamcrest.Matchers.instanceOf;
 
 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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
                 .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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
                 .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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
      */
     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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
             "    }\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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
      */
     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 class LegacyGeoShapeIntegrationIT extends ESIntegTestCase {
     }
 
     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();
 

+ 6 - 0
server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java

@@ -27,6 +27,7 @@ import java.io.IOException;
 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 class GeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<Geomet
         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<String> 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(),

+ 5 - 0
server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java

@@ -47,6 +47,7 @@ import java.util.Map;
 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 class LegacyGeoShapeFieldMapper extends AbstractShapeGeometryFieldMapper<
         return DEPRECATED_PARAMETERS.stream().anyMatch(paramKeys::contains);
     }
 
+    public static Set<String> getDeprecatedParameters(Set<String> 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";

+ 3 - 1
server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java

@@ -291,8 +291,10 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase {
 
         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());

+ 12 - 4
server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java

@@ -35,6 +35,7 @@ import org.elasticsearch.index.mapper.ContentPath;
 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 class GeoWKTShapeParserTests extends BaseGeoParsingTestCase {
         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 class GeoWKTShapeParserTests extends BaseGeoParsingTestCase {
         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 class GeoWKTShapeParserTests extends BaseGeoParsingTestCase {
         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());

+ 1 - 3
server/src/test/java/org/elasticsearch/index/mapper/FieldFilterMapperPluginTests.java

@@ -297,9 +297,7 @@ public class FieldFilterMapperPluginTests extends ESSingleNodeTestCase {
             "              \"type\": \"geo_point\"\n" +
             "            },\n" +
             "            \"area_visible\": {\n" +
-            "              \"type\": \"geo_shape\",  \n" +
-            "              \"tree\": \"quadtree\",\n" +
-            "              \"precision\": \"1m\"\n" +
+            "              \"type\": \"geo_shape\"" +
             "            }\n" +
             "          }\n" +
             "        },\n" +

+ 5 - 2
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 class GeoShapeFieldMapperTests extends MapperTestCase {
     }
 
     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 class GeoShapeFieldMapperTests extends MapperTestCase {
             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(),

+ 25 - 0
server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapperTests.java

@@ -13,6 +13,7 @@ import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
 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.geometry.Point;
 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 @@ public class LegacyGeoShapeFieldMapperTests extends MapperTestCase {
         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

+ 3 - 2
server/src/test/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldTypeTests.java

@@ -10,6 +10,7 @@ package org.elasticsearch.index.mapper;
 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 class LegacyGeoShapeFieldTypeTests extends FieldTypeTestCase {
     }
 
     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<String, Object> jsonLineString = Map.of("type", "LineString", "coordinates",

+ 76 - 44
server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java

@@ -10,6 +10,7 @@ package org.elasticsearch.search.geo;
 
 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.mapper.MapperParsingException;
 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 @@ public class GeoShapeQueryTests extends GeoQueryTests {
         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 @@ public class GeoShapeQueryTests extends GeoQueryTests {
         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 class GeoShapeQueryTests extends GeoQueryTests {
     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 class GeoShapeQueryTests extends GeoQueryTests {
 
         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 class GeoShapeQueryTests extends GeoQueryTests {
     }
 
     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 class GeoShapeQueryTests extends GeoQueryTests {
         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 class GeoShapeQueryTests extends GeoQueryTests {
             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 class GeoShapeQueryTests extends GeoQueryTests {
         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 class GeoShapeQueryTests extends GeoQueryTests {
                 .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 class GeoShapeQueryTests extends GeoQueryTests {
             .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 class GeoShapeQueryTests extends GeoQueryTests {
     }
 
     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 class GeoShapeQueryTests extends GeoQueryTests {
             .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 class GeoShapeQueryTests extends GeoQueryTests {
 
     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 class GeoShapeQueryTests extends GeoQueryTests {
 
         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 class GeoShapeQueryTests extends GeoQueryTests {
     }
 
     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 class GeoShapeQueryTests extends GeoQueryTests {
     }
 
     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 class GeoShapeQueryTests extends GeoQueryTests {
     }
 
     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));
 

+ 1 - 1
test/framework/src/main/java/org/elasticsearch/index/mapper/MapperServiceTestCase.java

@@ -152,7 +152,7 @@ public abstract class MapperServiceTestCase extends ESTestCase {
         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);
     }
 

+ 6 - 0
x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java

@@ -44,6 +44,7 @@ import java.io.IOException;
 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 class GeoShapeWithDocValuesFieldMapper extends AbstractShapeGeometryField
         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<String> 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(),

+ 13 - 0
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapperTests.java

@@ -26,6 +26,7 @@ import org.elasticsearch.common.xcontent.XContentType;
 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.io.IOException;
 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 class GeoShapeWithDocValuesFieldMapperTests extends MapperTestCase {
         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"));