99import org .apache .lucene .index .IndexableField ;
1010import org .apache .lucene .util .BytesRef ;
1111import org .elasticsearch .common .Strings ;
12+ import org .elasticsearch .common .geo .GeoJson ;
1213import org .elasticsearch .common .geo .Orientation ;
14+ import org .elasticsearch .common .geo .ShapeRelation ;
15+ import org .elasticsearch .common .geo .SpatialStrategy ;
16+ import org .elasticsearch .geo .GeometryTestUtils ;
1317import org .elasticsearch .geometry .Geometry ;
18+ import org .elasticsearch .geometry .MultiPoint ;
19+ import org .elasticsearch .geometry .Point ;
1420import org .elasticsearch .geometry .utils .GeometryValidator ;
1521import org .elasticsearch .geometry .utils .WellKnownBinary ;
1622import org .elasticsearch .geometry .utils .WellKnownText ;
2733import org .elasticsearch .index .mapper .MapperService ;
2834import org .elasticsearch .index .mapper .ParsedDocument ;
2935import org .elasticsearch .index .mapper .SourceToParse ;
36+ import org .elasticsearch .index .query .SearchExecutionContext ;
37+ import org .elasticsearch .legacygeo .mapper .LegacyGeoShapeFieldMapper ;
38+ import org .elasticsearch .legacygeo .mapper .LegacyGeoShapeFieldMapper .GeoShapeFieldType ;
3039import org .elasticsearch .test .index .IndexVersionUtils ;
31- import org .elasticsearch .xcontent .ToXContent ;
40+ import org .elasticsearch .xcontent .ToXContent .MapParams ;
41+ import org .elasticsearch .xcontent .ToXContent .Params ;
42+ import org .elasticsearch .xpack .spatial .index .mapper .GeometricShapeSyntheticSourceSupport .FieldType ;
3243import org .junit .AssumptionViolatedException ;
3344
3445import java .io .IOException ;
3546import java .util .Collections ;
3647import java .util .List ;
48+ import java .util .Set ;
3749import java .util .function .Function ;
3850
51+ import static org .elasticsearch .legacygeo .mapper .LegacyGeoShapeFieldMapper .DEPRECATED_PARAMETERS ;
3952import static org .hamcrest .Matchers .containsString ;
4053import static org .hamcrest .Matchers .equalTo ;
4154import static org .hamcrest .Matchers .hasSize ;
4255import static org .hamcrest .Matchers .instanceOf ;
56+ import static org .mockito .Mockito .mock ;
57+ import static org .mockito .Mockito .when ;
4358
4459public class GeoShapeWithDocValuesFieldMapperTests extends GeoFieldMapperTests {
4560
@@ -289,6 +304,75 @@ public void testInvalidCurrentVersion() {
289304 );
290305 }
291306
307+ /**
308+ * Test that we can parse legacy v7 "geo_shape" parameters for BWC with read-only N-2 indices
309+ */
310+ public void testGeoShapeLegacyParametersParsing () throws Exception {
311+ // deprecated parameters needed for bwc with read-only version 7 indices
312+ assertEquals (Set .of ("strategy" , "tree" , "tree_levels" , "precision" , "distance_error_pct" , "points_only" ), DEPRECATED_PARAMETERS );
313+
314+ for (String deprecatedParam : DEPRECATED_PARAMETERS ) {
315+ Object value = switch (deprecatedParam ) {
316+ case "tree" -> randomFrom ("quadtree" , "geohash" );
317+ case "tree_levels" -> 6 ;
318+ case "distance_error_pct" -> "0.01" ;
319+ case "points_only" -> true ;
320+ case "strategy" -> "recursive" ;
321+ case "precision" -> "50m" ;
322+ default -> throw new IllegalStateException ("Unexpected value: " + deprecatedParam );
323+ };
324+
325+ // indices created before 8 should allow parameters but issue a warning
326+ IndexVersion pre8version = IndexVersionUtils .randomPreviousCompatibleVersion (random (), IndexVersions .V_8_0_0 );
327+ MapperService m = createMapperService (
328+ pre8version ,
329+ fieldMapping (b -> b .field ("type" , getFieldName ()).field (deprecatedParam , value ))
330+ );
331+
332+ // check mapper
333+ Mapper mapper = m .mappingLookup ().getMapper ("field" );
334+ assertThat (mapper , instanceOf (LegacyGeoShapeFieldMapper .class ));
335+
336+ // check document parsing
337+ MultiPoint multiPoint = GeometryTestUtils .randomMultiPoint (false );
338+ assertNotNull (m .documentMapper ().parse (source (b -> {
339+ b .field ("field" );
340+ GeoJson .toXContent (multiPoint , b , null );
341+ })));
342+
343+ // check for correct field type and that a query can be created
344+ MappedFieldType fieldType = m .fieldType ("field" );
345+ assertThat (fieldType , instanceOf (GeoShapeFieldType .class ));
346+ GeoShapeFieldType ft = (GeoShapeFieldType ) fieldType ;
347+
348+ SearchExecutionContext searchExecutionContext = mock (SearchExecutionContext .class );
349+ when (searchExecutionContext .allowExpensiveQueries ()).thenReturn (true );
350+ assertNotNull (
351+ ft .geoShapeQuery (searchExecutionContext , "location" , SpatialStrategy .TERM , ShapeRelation .INTERSECTS , new Point (-10 , 10 ))
352+ );
353+ if (deprecatedParam .equals ("strategy" ) == false ) {
354+ assertFieldWarnings (deprecatedParam , "strategy" );
355+ } else {
356+ assertFieldWarnings (deprecatedParam );
357+ }
358+
359+ // indices created after 8 should throw an error
360+ IndexVersion post8version = IndexVersionUtils .randomCompatibleWriteVersion (random ());
361+ Exception ex = expectThrows (
362+ MapperParsingException .class ,
363+ () -> createMapperService (post8version , fieldMapping (b -> b .field ("type" , getFieldName ()).field (deprecatedParam , value )))
364+ );
365+ assertThat (
366+ ex .getMessage (),
367+ containsString (
368+ "Failed to parse mapping: using deprecated parameters ["
369+ + deprecatedParam
370+ + "] in mapper [field] of type [geo_shape] is no longer allowed"
371+ )
372+ );
373+ }
374+ }
375+
292376 public void testGeoShapeLegacyMerge () throws Exception {
293377 IndexVersion version = IndexVersionUtils .randomPreviousCompatibleVersion (random (), IndexVersions .V_8_0_0 );
294378 MapperService m = createMapperService (version , fieldMapping (b -> b .field ("type" , getFieldName ())));
@@ -409,7 +493,7 @@ public void testSelfIntersectPolygon() throws IOException {
409493
410494 public String toXContentString (AbstractShapeGeometryFieldMapper <?> mapper , boolean includeDefaults ) {
411495 if (includeDefaults ) {
412- ToXContent . Params params = new ToXContent . MapParams (Collections .singletonMap ("include_defaults" , "true" ));
496+ Params params = new MapParams (Collections .singletonMap ("include_defaults" , "true" ));
413497 return Strings .toString (mapper , params );
414498 } else {
415499 return Strings .toString (mapper );
@@ -428,7 +512,7 @@ protected Object generateRandomInputValue(MappedFieldType ft) {
428512
429513 @ Override
430514 protected SyntheticSourceSupport syntheticSourceSupport (boolean ignoreMalformed ) {
431- return new GeometricShapeSyntheticSourceSupport (GeometricShapeSyntheticSourceSupport . FieldType .GEO_SHAPE , ignoreMalformed );
515+ return new GeometricShapeSyntheticSourceSupport (FieldType .GEO_SHAPE , ignoreMalformed );
432516 }
433517
434518 @ Override
0 commit comments