Skip to content

Commit 0130139

Browse files
authored
Geo: Fix handling of circles in legacy geo_shape queries (#49410)
Brings back support for circles in legacy geo_shape queries that was accidentally lost during query refactoring. Fixes #49296
1 parent 5e60c7d commit 0130139

File tree

5 files changed

+45
-7
lines changed

5 files changed

+45
-7
lines changed

server/src/main/java/org/elasticsearch/common/geo/GeometryIO.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.elasticsearch.common.io.stream.StreamInput;
2323
import org.elasticsearch.common.io.stream.StreamOutput;
24+
import org.elasticsearch.common.unit.DistanceUnit;
2425
import org.elasticsearch.geometry.Circle;
2526
import org.elasticsearch.geometry.Geometry;
2627
import org.elasticsearch.geometry.GeometryCollection;
@@ -49,7 +50,10 @@ public static void writeGeometry(StreamOutput out, Geometry geometry) throws IOE
4950
geometry.visit(new GeometryVisitor<Void, IOException>() {
5051
@Override
5152
public Void visit(Circle circle) throws IOException {
52-
throw new UnsupportedOperationException("circle is not supported");
53+
writeCoordinate(circle.getLat(), circle.getLon(), circle.getAlt());
54+
out.writeDouble(circle.getRadiusMeters());
55+
DistanceUnit.METERS.writeTo(out);
56+
return null;
5357
}
5458

5559
@Override
@@ -161,6 +165,8 @@ public static Geometry readGeometry(StreamInput in) throws IOException {
161165
return readMultiPolygon(in);
162166
case "envelope":
163167
return readRectangle(in);
168+
case "circle":
169+
return readCircle(in);
164170
default:
165171
throw new UnsupportedOperationException("unsupported shape type " + type);
166172
}
@@ -304,4 +310,13 @@ private static double readAlt(StreamInput in) throws IOException {
304310
return alt;
305311
}
306312
}
313+
314+
private static Circle readCircle(StreamInput in) throws IOException {
315+
double lon = in.readDouble();
316+
double lat = in.readDouble();
317+
double alt = readAlt(in);
318+
double radius = in.readDouble();
319+
DistanceUnit distanceUnit = DistanceUnit.readFromStream(in);
320+
return new Circle(lon, lat, alt, distanceUnit.toMeters(radius));
321+
}
307322
}

server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public Circle buildS4J() {
165165

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

171171
@Override

server/src/main/java/org/elasticsearch/index/query/LegacyGeoShapeQueryProcessor.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.lucene.spatial.query.SpatialOperation;
2929
import org.elasticsearch.common.geo.ShapeRelation;
3030
import org.elasticsearch.common.geo.SpatialStrategy;
31+
import org.elasticsearch.common.geo.builders.CircleBuilder;
3132
import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
3233
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
3334
import org.elasticsearch.common.geo.builders.LineStringBuilder;
@@ -37,6 +38,7 @@
3738
import org.elasticsearch.common.geo.builders.PointBuilder;
3839
import org.elasticsearch.common.geo.builders.PolygonBuilder;
3940
import org.elasticsearch.common.geo.builders.ShapeBuilder;
41+
import org.elasticsearch.common.unit.DistanceUnit;
4042
import org.elasticsearch.geometry.Circle;
4143
import org.elasticsearch.geometry.Geometry;
4244
import org.elasticsearch.geometry.GeometryCollection;
@@ -123,7 +125,7 @@ private static Shape buildS4J(Geometry geometry) {
123125
ShapeBuilder<?, ?, ?> shapeBuilder = geometry.visit(new GeometryVisitor<>() {
124126
@Override
125127
public ShapeBuilder<?, ?, ?> visit(Circle circle) {
126-
throw new UnsupportedOperationException("circle is not supported");
128+
return new CircleBuilder().center(circle.getLon(), circle.getLat()).radius(circle.getRadiusMeters(), DistanceUnit.METERS);
127129
}
128130

129131
@Override

server/src/test/java/org/elasticsearch/common/geo/GeometryIOTests.java

-4
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ private boolean shapeSupported(Geometry geometry) {
8888
return false;
8989
}
9090

91-
if (geometry.type() == ShapeType.CIRCLE) {
92-
return false;
93-
}
94-
9591
if (geometry.type() == ShapeType.GEOMETRYCOLLECTION) {
9692
GeometryCollection<?> collection = (GeometryCollection<?>) geometry;
9793
for (Geometry g : collection) {

server/src/test/java/org/elasticsearch/search/geo/LegacyGeoShapeIntegrationIT.java

+25
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import org.elasticsearch.cluster.routing.IndexShardRoutingTable;
2424
import org.elasticsearch.common.Strings;
2525
import org.elasticsearch.common.geo.builders.ShapeBuilder;
26+
import org.elasticsearch.common.xcontent.ToXContent;
2627
import org.elasticsearch.common.xcontent.XContentFactory;
2728
import org.elasticsearch.common.xcontent.XContentType;
29+
import org.elasticsearch.geometry.Circle;
2830
import org.elasticsearch.index.IndexService;
2931
import org.elasticsearch.index.mapper.LegacyGeoShapeFieldMapper;
3032
import org.elasticsearch.index.mapper.MappedFieldType;
@@ -161,6 +163,29 @@ public void testIndexShapeRouting() throws Exception {
161163
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
162164
}
163165

166+
/**
167+
* Test that the circle is still supported for the legacy shapes
168+
*/
169+
public void testLegacyCircle() throws Exception {
170+
// create index
171+
assertAcked(client().admin().indices().prepareCreate("test")
172+
.addMapping("geometry", "shape", "type=geo_shape,strategy=recursive,tree=geohash").get());
173+
ensureGreen();
174+
175+
indexRandom(true, client().prepareIndex("test").setId("0").setSource("shape", (ToXContent) (builder, params) -> {
176+
builder.startObject().field("type", "circle")
177+
.startArray("coordinates").value(30).value(50).endArray()
178+
.field("radius","77km")
179+
.endObject();
180+
return builder;
181+
}));
182+
183+
// test self crossing of circles
184+
SearchResponse searchResponse = client().prepareSearch("test").setQuery(geoShapeQuery("shape",
185+
new Circle(30, 50, 77000))).get();
186+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
187+
}
188+
164189
private String findNodeName(String index) {
165190
ClusterState state = client().admin().cluster().prepareState().get().getState();
166191
IndexShardRoutingTable shard = state.getRoutingTable().index(index).shard(0);

0 commit comments

Comments
 (0)