Skip to content

Commit

Permalink
Geo: Fix handling of circles in legacy geo_shape queries (#49410)
Browse files Browse the repository at this point in the history
Brings back support for circles in legacy geo_shape queries that
was accidentally lost during query refactoring.

Fixes #49296
  • Loading branch information
imotov committed Nov 21, 2019
1 parent 8543bf2 commit 4cb0032
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.geometry.Circle;
import org.elasticsearch.geometry.Geometry;
import org.elasticsearch.geometry.GeometryCollection;
Expand Down Expand Up @@ -49,7 +50,10 @@ public static void writeGeometry(StreamOutput out, Geometry geometry) throws IOE
geometry.visit(new GeometryVisitor<Void, IOException>() {
@Override
public Void visit(Circle circle) throws IOException {
throw new UnsupportedOperationException("circle is not supported");
writeCoordinate(circle.getLat(), circle.getLon(), circle.getAlt());
out.writeDouble(circle.getRadiusMeters());
DistanceUnit.METERS.writeTo(out);
return null;
}

@Override
Expand Down Expand Up @@ -161,6 +165,8 @@ public static Geometry readGeometry(StreamInput in) throws IOException {
return readMultiPolygon(in);
case "envelope":
return readRectangle(in);
case "circle":
return readCircle(in);
default:
throw new UnsupportedOperationException("unsupported shape type " + type);
}
Expand Down Expand Up @@ -304,4 +310,13 @@ private static double readAlt(StreamInput in) throws IOException {
return alt;
}
}

private static Circle readCircle(StreamInput in) throws IOException {
double lon = in.readDouble();
double lat = in.readDouble();
double alt = readAlt(in);
double radius = in.readDouble();
DistanceUnit distanceUnit = DistanceUnit.readFromStream(in);
return new Circle(lon, lat, alt, distanceUnit.toMeters(radius));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public Circle buildS4J() {

@Override
public org.elasticsearch.geometry.Circle buildGeometry() {
throw new UnsupportedOperationException("CIRCLE geometry is not supported");
return new org.elasticsearch.geometry.Circle(center.x, center.y, unit.toMeters(radius));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.lucene.spatial.query.SpatialOperation;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.SpatialStrategy;
import org.elasticsearch.common.geo.builders.CircleBuilder;
import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
Expand All @@ -37,6 +38,7 @@
import org.elasticsearch.common.geo.builders.PointBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.geometry.Circle;
import org.elasticsearch.geometry.Geometry;
import org.elasticsearch.geometry.GeometryCollection;
Expand Down Expand Up @@ -123,7 +125,7 @@ private static Shape buildS4J(Geometry geometry) {
ShapeBuilder<?, ?, ?> shapeBuilder = geometry.visit(new GeometryVisitor<ShapeBuilder<?, ?, ?>, RuntimeException>() {
@Override
public ShapeBuilder<?, ?, ?> visit(Circle circle) {
throw new UnsupportedOperationException("circle is not supported");
return new CircleBuilder().center(circle.getLon(), circle.getLat()).radius(circle.getRadiusMeters(), DistanceUnit.METERS);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ private boolean shapeSupported(Geometry geometry) {
return false;
}

if (geometry.type() == ShapeType.CIRCLE) {
return false;
}

if (geometry.type() == ShapeType.GEOMETRYCOLLECTION) {
GeometryCollection<?> collection = (GeometryCollection<?>) geometry;
for (Geometry g : collection) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import org.elasticsearch.cluster.routing.IndexShardRoutingTable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.geometry.Circle;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
Expand Down Expand Up @@ -161,6 +163,29 @@ public void testIndexShapeRouting() throws Exception {
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
}

/**
* Test that the circle is still supported for the legacy shapes
*/
public void testLegacyCircle() throws Exception {
// create index
assertAcked(client().admin().indices().prepareCreate("test")
.addMapping("geometry", "shape", "type=geo_shape,strategy=recursive,tree=geohash").get());
ensureGreen();

indexRandom(true, client().prepareIndex("test", "_doc", "0").setSource("shape", (ToXContent) (builder, params) -> {
builder.startObject().field("type", "circle")
.startArray("coordinates").value(30).value(50).endArray()
.field("radius","77km")
.endObject();
return builder;
}));

// test self crossing of circles
SearchResponse searchResponse = client().prepareSearch("test").setQuery(geoShapeQuery("shape",
new Circle(30, 50, 77000))).get();
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
}

private String findNodeName(String index) {
ClusterState state = client().admin().cluster().prepareState().get().getState();
IndexShardRoutingTable shard = state.getRoutingTable().index(index).shard(0);
Expand Down

0 comments on commit 4cb0032

Please sign in to comment.