[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.
This commit is contained in:
Nicholas Knize 2017-11-16 15:09:23 -06:00
parent 858b2c7cb8
commit 075c77fc81
2 changed files with 58 additions and 9 deletions

View File

@ -34,6 +34,7 @@ import org.elasticsearch.Version;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.geo.SpatialStrategy;
import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
import org.elasticsearch.common.geo.parsers.ShapeParser;
@ -463,7 +464,6 @@ public class GeoShapeFieldMapper extends FieldMapper {
public GeoShapeFieldType fieldType() {
return (GeoShapeFieldType) super.fieldType();
}
@Override
public Mapper parse(ParseContext context) throws IOException {
try {
@ -475,14 +475,20 @@ public class GeoShapeFieldMapper extends FieldMapper {
}
shape = shapeBuilder.build();
}
if (fieldType().pointsOnly() && !(shape instanceof Point)) {
throw new MapperParsingException("[{" + fieldType().name() + "}] is configured for points only but a " +
((shape instanceof JtsGeometry) ? ((JtsGeometry) shape).getGeom().getGeometryType() : shape.getClass()) + " was found");
}
List<IndexableField> fields = new ArrayList<>(Arrays.asList(fieldType().defaultStrategy().createIndexableFields(shape)));
createFieldNamesField(context, fields);
for (IndexableField field : fields) {
context.doc().add(field);
if (fieldType().pointsOnly() == true) {
// index configured for pointsOnly
if (shape instanceof XShapeCollection && XShapeCollection.class.cast(shape).pointsOnly()) {
// MULTIPOINT data: index each point separately
List<Shape> shapes = ((XShapeCollection) shape).getShapes();
for (Shape s : shapes) {
indexShape(context, s);
}
} else if (shape instanceof Point == false) {
throw new MapperParsingException("[{" + fieldType().name() + "}] is configured for points only but a " +
((shape instanceof JtsGeometry) ? ((JtsGeometry)shape).getGeom().getGeometryType() : shape.getClass()) + " was found");
}
} else {
indexShape(context, shape);
}
} catch (Exception e) {
if (ignoreMalformed.value() == false) {
@ -492,6 +498,14 @@ public class GeoShapeFieldMapper extends FieldMapper {
return null;
}
private void indexShape(ParseContext context, Shape shape) {
List<IndexableField> fields = new ArrayList<>(Arrays.asList(fieldType().defaultStrategy().createIndexableFields(shape)));
createFieldNamesField(context, fields);
for (IndexableField field : fields) {
context.doc().add(field);
}
}
@Override
protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException {
}

View File

@ -48,6 +48,7 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDI
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.QueryBuilders.geoIntersectionQuery;
import static org.elasticsearch.index.query.QueryBuilders.geoShapeQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.test.geo.RandomShapeGenerator.createGeometryCollectionWithin;
import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint;
import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle;
@ -468,4 +469,38 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
assertEquals(1, response.getHits().getTotalHits());
}
public void testPointsOnlyExplicit() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type1")
.startObject("properties").startObject("location")
.field("type", "geo_shape")
.field("tree", randomBoolean() ? "quadtree" : "geohash")
.field("tree_levels", "6")
.field("distance_error_pct", "0.01")
.field("points_only", true)
.endObject().endObject()
.endObject().endObject().string();
client().admin().indices().prepareCreate("geo_points_only").addMapping("type1", mapping, XContentType.JSON).execute().actionGet();
ensureGreen();
// MULTIPOINT
ShapeBuilder shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.MULTIPOINT);
client().prepareIndex("geo_points_only", "type1", "1")
.setSource(jsonBuilder().startObject().field("location", shape).endObject())
.setRefreshPolicy(IMMEDIATE).get();
// POINT
shape = RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.POINT);
client().prepareIndex("geo_points_only", "type1", "2")
.setSource(jsonBuilder().startObject().field("location", shape).endObject())
.setRefreshPolicy(IMMEDIATE).get();
// test that point was inserted
SearchResponse response = client().prepareSearch("geo_points_only").setTypes("type1")
.setQuery(matchAllQuery())
.execute().actionGet();
assertEquals(2, response.getHits().getTotalHits());
}
}