26
26
import org .elasticsearch .Version ;
27
27
import org .elasticsearch .common .Explicit ;
28
28
import org .elasticsearch .common .ParseField ;
29
+ import org .elasticsearch .common .geo .ShapeRelation ;
30
+ import org .elasticsearch .common .geo .SpatialStrategy ;
29
31
import org .elasticsearch .common .geo .builders .ShapeBuilder ;
30
32
import org .elasticsearch .common .geo .builders .ShapeBuilder .Orientation ;
31
33
import org .elasticsearch .common .settings .Settings ;
32
34
import org .elasticsearch .common .xcontent .LoggingDeprecationHandler ;
33
35
import org .elasticsearch .common .xcontent .XContentBuilder ;
36
+ import org .elasticsearch .common .xcontent .XContentParser ;
34
37
import org .elasticsearch .common .xcontent .support .XContentMapValues ;
38
+ import org .elasticsearch .geo .geometry .Geometry ;
35
39
import org .elasticsearch .index .mapper .LegacyGeoShapeFieldMapper .DeprecatedParameters ;
36
40
import org .elasticsearch .index .query .QueryShardContext ;
37
41
import org .elasticsearch .index .query .QueryShardException ;
38
42
39
43
import java .io .IOException ;
44
+ import java .text .ParseException ;
40
45
import java .util .Iterator ;
41
46
import java .util .List ;
42
47
import java .util .Map ;
47
52
/**
48
53
* Base class for {@link GeoShapeFieldMapper} and {@link LegacyGeoShapeFieldMapper}
49
54
*/
50
- public abstract class BaseGeoShapeFieldMapper extends FieldMapper {
51
- public static final String CONTENT_TYPE = "geo_shape" ;
55
+ public abstract class AbstractGeometryFieldMapper < Parsed , Processed > extends FieldMapper {
56
+
52
57
53
58
public static class Names {
54
59
public static final ParseField ORIENTATION = new ParseField ("orientation" );
@@ -62,7 +67,36 @@ public static class Defaults {
62
67
public static final Explicit <Boolean > IGNORE_Z_VALUE = new Explicit <>(true , false );
63
68
}
64
69
65
- public abstract static class Builder <T extends Builder , Y extends BaseGeoShapeFieldMapper >
70
+
71
+ /**
72
+ * Interface representing an preprocessor in geo-shape indexing pipeline
73
+ */
74
+ public interface Indexer <Parsed , Processed > {
75
+
76
+ Processed prepareForIndexing (Parsed geometry );
77
+
78
+ Class <Processed > processedClass ();
79
+
80
+ }
81
+
82
+ /**
83
+ * interface representing parser in geo shape indexing pipeline
84
+ */
85
+ public interface Parser <Parsed > {
86
+
87
+ Parsed parse (XContentParser parser , AbstractGeometryFieldMapper mapper ) throws IOException , ParseException ;
88
+
89
+ }
90
+
91
+ /**
92
+ * interface representing a query builder that generates a query from the given shape
93
+ */
94
+ public interface QueryProcessor {
95
+
96
+ Query process (Geometry shape , String fieldName , SpatialStrategy strategy , ShapeRelation relation , QueryShardContext context );
97
+ }
98
+
99
+ public abstract static class Builder <T extends Builder , Y extends AbstractGeometryFieldMapper >
66
100
extends FieldMapper .Builder <T , Y > {
67
101
protected Boolean coerce ;
68
102
protected Boolean ignoreMalformed ;
@@ -152,7 +186,7 @@ protected void setupFieldType(BuilderContext context) {
152
186
throw new IllegalArgumentException ("name cannot be empty string" );
153
187
}
154
188
155
- BaseGeoShapeFieldType ft = (BaseGeoShapeFieldType )fieldType ();
189
+ AbstractGeometryFieldType ft = (AbstractGeometryFieldType )fieldType ();
156
190
ft .setOrientation (orientation ().value ());
157
191
}
158
192
}
@@ -218,26 +252,32 @@ public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext
218
252
}
219
253
}
220
254
221
- public abstract static class BaseGeoShapeFieldType extends MappedFieldType {
255
+ public abstract static class AbstractGeometryFieldType < Parsed , Processed > extends MappedFieldType {
222
256
protected Orientation orientation = Defaults .ORIENTATION .value ();
223
257
224
- protected BaseGeoShapeFieldType () {
258
+ protected Indexer <Parsed , Processed > geometryIndexer ;
259
+
260
+ protected Parser <Parsed > geometryParser ;
261
+
262
+ protected QueryProcessor geometryQueryBuilder ;
263
+
264
+ protected AbstractGeometryFieldType () {
225
265
setIndexOptions (IndexOptions .DOCS );
226
266
setTokenized (false );
227
267
setStored (false );
228
268
setStoreTermVectors (false );
229
269
setOmitNorms (true );
230
270
}
231
271
232
- protected BaseGeoShapeFieldType ( BaseGeoShapeFieldType ref ) {
272
+ protected AbstractGeometryFieldType ( AbstractGeometryFieldType ref ) {
233
273
super (ref );
234
274
this .orientation = ref .orientation ;
235
275
}
236
276
237
277
@ Override
238
278
public boolean equals (Object o ) {
239
279
if (!super .equals (o )) return false ;
240
- BaseGeoShapeFieldType that = (BaseGeoShapeFieldType ) o ;
280
+ AbstractGeometryFieldType that = (AbstractGeometryFieldType ) o ;
241
281
return orientation == that .orientation ;
242
282
}
243
283
@@ -246,16 +286,6 @@ public int hashCode() {
246
286
return Objects .hash (super .hashCode (), orientation );
247
287
}
248
288
249
- @ Override
250
- public String typeName () {
251
- return CONTENT_TYPE ;
252
- }
253
-
254
- @ Override
255
- public void checkCompatibility (MappedFieldType fieldType , List <String > conflicts ) {
256
- super .checkCompatibility (fieldType , conflicts );
257
- }
258
-
259
289
public Orientation orientation () { return this .orientation ; }
260
290
261
291
public void setOrientation (Orientation orientation ) {
@@ -272,16 +302,40 @@ public Query existsQuery(QueryShardContext context) {
272
302
public Query termQuery (Object value , QueryShardContext context ) {
273
303
throw new QueryShardException (context , "Geo fields do not support exact searching, use dedicated geo queries instead" );
274
304
}
305
+
306
+ public void setGeometryIndexer (Indexer <Parsed , Processed > geometryIndexer ) {
307
+ this .geometryIndexer = geometryIndexer ;
308
+ }
309
+
310
+ protected Indexer <Parsed , Processed > geometryIndexer () {
311
+ return geometryIndexer ;
312
+ }
313
+
314
+ public void setGeometryParser (Parser <Parsed > geometryParser ) {
315
+ this .geometryParser = geometryParser ;
316
+ }
317
+
318
+ protected Parser <Parsed > geometryParser () {
319
+ return geometryParser ;
320
+ }
321
+
322
+ public void setGeometryQueryBuilder (QueryProcessor geometryQueryBuilder ) {
323
+ this .geometryQueryBuilder = geometryQueryBuilder ;
324
+ }
325
+
326
+ public QueryProcessor geometryQueryBuilder () {
327
+ return geometryQueryBuilder ;
328
+ }
275
329
}
276
330
277
331
protected Explicit <Boolean > coerce ;
278
332
protected Explicit <Boolean > ignoreMalformed ;
279
333
protected Explicit <Boolean > ignoreZValue ;
280
334
281
- protected BaseGeoShapeFieldMapper (String simpleName , MappedFieldType fieldType , MappedFieldType defaultFieldType ,
282
- Explicit <Boolean > ignoreMalformed , Explicit <Boolean > coerce ,
283
- Explicit <Boolean > ignoreZValue , Settings indexSettings ,
284
- MultiFields multiFields , CopyTo copyTo ) {
335
+ protected AbstractGeometryFieldMapper (String simpleName , MappedFieldType fieldType , MappedFieldType defaultFieldType ,
336
+ Explicit <Boolean > ignoreMalformed , Explicit <Boolean > coerce ,
337
+ Explicit <Boolean > ignoreZValue , Settings indexSettings ,
338
+ MultiFields multiFields , CopyTo copyTo ) {
285
339
super (simpleName , fieldType , defaultFieldType , indexSettings , multiFields , copyTo );
286
340
this .coerce = coerce ;
287
341
this .ignoreMalformed = ignoreMalformed ;
@@ -291,7 +345,7 @@ protected BaseGeoShapeFieldMapper(String simpleName, MappedFieldType fieldType,
291
345
@ Override
292
346
protected void doMerge (Mapper mergeWith ) {
293
347
super .doMerge (mergeWith );
294
- BaseGeoShapeFieldMapper gsfm = (BaseGeoShapeFieldMapper )mergeWith ;
348
+ AbstractGeometryFieldMapper gsfm = (AbstractGeometryFieldMapper )mergeWith ;
295
349
if (gsfm .coerce .explicit ()) {
296
350
this .coerce = gsfm .coerce ;
297
351
}
@@ -310,7 +364,7 @@ protected void parseCreateField(ParseContext context, List<IndexableField> field
310
364
@ Override
311
365
protected void doXContentBody (XContentBuilder builder , boolean includeDefaults , Params params ) throws IOException {
312
366
builder .field ("type" , contentType ());
313
- BaseGeoShapeFieldType ft = (BaseGeoShapeFieldType )fieldType ();
367
+ AbstractGeometryFieldType ft = (AbstractGeometryFieldType )fieldType ();
314
368
if (includeDefaults || ft .orientation () != Defaults .ORIENTATION .value ()) {
315
369
builder .field (Names .ORIENTATION .getPreferredName (), ft .orientation ());
316
370
}
@@ -338,11 +392,35 @@ public Explicit<Boolean> ignoreZValue() {
338
392
}
339
393
340
394
public Orientation orientation () {
341
- return ((BaseGeoShapeFieldType )fieldType ).orientation ();
395
+ return ((AbstractGeometryFieldType )fieldType ).orientation ();
342
396
}
343
397
398
+ protected abstract void indexShape (ParseContext context , Processed shape );
399
+
400
+ /** parsing logic for geometry indexing */
344
401
@ Override
345
- protected String contentType () {
346
- return CONTENT_TYPE ;
402
+ public void parse (ParseContext context ) throws IOException {
403
+ AbstractGeometryFieldType fieldType = (AbstractGeometryFieldType )fieldType ();
404
+
405
+ @ SuppressWarnings ("unchecked" ) Indexer <Parsed , Processed > geometryIndexer = fieldType .geometryIndexer ();
406
+ @ SuppressWarnings ("unchecked" ) Parser <Parsed > geometryParser = fieldType .geometryParser ();
407
+ try {
408
+ Processed shape = context .parseExternalValue (geometryIndexer .processedClass ());
409
+ if (shape == null ) {
410
+ Parsed geometry = geometryParser .parse (context .parser (), this );
411
+ if (geometry == null ) {
412
+ return ;
413
+ }
414
+ shape = geometryIndexer .prepareForIndexing (geometry );
415
+ }
416
+ indexShape (context , shape );
417
+ } catch (Exception e ) {
418
+ if (ignoreMalformed .value () == false ) {
419
+ throw new MapperParsingException ("failed to parse field [{}] of type [{}]" , e , fieldType ().name (),
420
+ fieldType ().typeName ());
421
+ }
422
+ context .addIgnoredField (fieldType ().name ());
423
+ }
347
424
}
425
+
348
426
}
0 commit comments