Skip to content

Commit 075c77f

Browse files
committed
[GEO] fix pointsOnly bug for MULTIPOINT
This commit fixes a bug where geo_shape indexes configured for "points_only" : "true" reject documents containing multipoint shape types.
1 parent 858b2c7 commit 075c77f

File tree

2 files changed

+58
-9
lines changed

2 files changed

+58
-9
lines changed

core/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.common.Explicit;
3535
import org.elasticsearch.common.geo.GeoUtils;
3636
import org.elasticsearch.common.geo.SpatialStrategy;
37+
import org.elasticsearch.common.geo.XShapeCollection;
3738
import org.elasticsearch.common.geo.builders.ShapeBuilder;
3839
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
3940
import org.elasticsearch.common.geo.parsers.ShapeParser;
@@ -463,7 +464,6 @@ public GeoShapeFieldMapper(String simpleName, MappedFieldType fieldType, Explici
463464
public GeoShapeFieldType fieldType() {
464465
return (GeoShapeFieldType) super.fieldType();
465466
}
466-
467467
@Override
468468
public Mapper parse(ParseContext context) throws IOException {
469469
try {
@@ -475,14 +475,20 @@ public Mapper parse(ParseContext context) throws IOException {
475475
}
476476
shape = shapeBuilder.build();
477477
}
478-
if (fieldType().pointsOnly() && !(shape instanceof Point)) {
479-
throw new MapperParsingException("[{" + fieldType().name() + "}] is configured for points only but a " +
480-
((shape instanceof JtsGeometry) ? ((JtsGeometry) shape).getGeom().getGeometryType() : shape.getClass()) + " was found");
481-
}
482-
List<IndexableField> fields = new ArrayList<>(Arrays.asList(fieldType().defaultStrategy().createIndexableFields(shape)));
483-
createFieldNamesField(context, fields);
484-
for (IndexableField field : fields) {
485-
context.doc().add(field);
478+
if (fieldType().pointsOnly() == true) {
479+
// index configured for pointsOnly
480+
if (shape instanceof XShapeCollection && XShapeCollection.class.cast(shape).pointsOnly()) {
481+
// MULTIPOINT data: index each point separately
482+
List<Shape> shapes = ((XShapeCollection) shape).getShapes();
483+
for (Shape s : shapes) {
484+
indexShape(context, s);
485+
}
486+
} else if (shape instanceof Point == false) {
487+
throw new MapperParsingException("[{" + fieldType().name() + "}] is configured for points only but a " +
488+
((shape instanceof JtsGeometry) ? ((JtsGeometry)shape).getGeom().getGeometryType() : shape.getClass()) + " was found");
489+
}
490+
} else {
491+
indexShape(context, shape);
486492
}
487493
} catch (Exception e) {
488494
if (ignoreMalformed.value() == false) {
@@ -492,6 +498,14 @@ public Mapper parse(ParseContext context) throws IOException {
492498
return null;
493499
}
494500

501+
private void indexShape(ParseContext context, Shape shape) {
502+
List<IndexableField> fields = new ArrayList<>(Arrays.asList(fieldType().defaultStrategy().createIndexableFields(shape)));
503+
createFieldNamesField(context, fields);
504+
for (IndexableField field : fields) {
505+
context.doc().add(field);
506+
}
507+
}
508+
495509
@Override
496510
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
497511
}

core/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
4949
import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery;
5050
import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery;
51+
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
5152
import static org.elasticsearch.test.geo.RandomShapeGenerator.createGeometryCollectionWithin;
5253
import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint;
5354
import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle;
@@ -468,4 +469,38 @@ public void testPointsOnly() throws Exception {
468469

469470
assertEquals(1, response.getHits().getTotalHits());
470471
}
472+
473+
public void testPointsOnlyExplicit() throws Exception {
474+
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type1")
475+
.startObject("properties").startObject("location")
476+
.field("type", "geo_shape")
477+
.field("tree", randomBoolean() ? "quadtree" : "geohash")
478+
.field("tree_levels", "6")
479+
.field("distance_error_pct", "0.01")
480+
.field("points_only", true)
481+
.endObject().endObject()
482+
.endObject().endObject().string();
483+
484+
client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).execute().actionGet();
485+
ensureGreen();
486+
487+
// MULTIPOINT
488+
ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT);
489+
client().prepareIndex("geo_points_only", "type1", "1")
490+
.setSource(jsonBuilder().startObject().field("location", shape).endObject())
491+
.setRefreshPolicy(IMMEDIATE).get();
492+
493+
// POINT
494+
shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.POINT);
495+
client().prepareIndex("geo_points_only", "type1", "2")
496+
.setSource(jsonBuilder().startObject().field("location", shape).endObject())
497+
.setRefreshPolicy(IMMEDIATE).get();
498+
499+
// test that point was inserted
500+
SearchResponse response = client().prepareSearch("geo_points_only").setTypes("type1")
501+
.setQuery(matchAllQuery())
502+
.execute().actionGet();
503+
504+
assertEquals(2, response.getHits().getTotalHits());
505+
}
471506
}

0 commit comments

Comments
 (0)