diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java index 9a103471a21a3..4dc368612c9aa 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.geo.GeoPolygonDecomposer; import org.elasticsearch.common.geo.GeoShapeUtils; import org.elasticsearch.common.geo.GeoShapeType; +import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.geometry.Circle; import org.elasticsearch.geometry.Geometry; import org.elasticsearch.geometry.GeometryCollection; @@ -261,7 +262,15 @@ public Void visit(Polygon polygon) { @Override public Void visit(Rectangle r) { - addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r))); + if (r.getMinLon() > r.getMaxLon()) { + Rectangle left = new Rectangle(r.getMinLon(), GeoUtils.MAX_LON, r.getMaxLat(), r.getMinLat()); + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(left))); + Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxLat(), r.getMinLat()); + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(right))); + + } else { + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r))); + } return null; } diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java index f5828aad13ee1..ddee41639cd3c 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.geo; +import org.apache.lucene.index.IndexableField; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; @@ -33,6 +34,7 @@ import org.elasticsearch.geometry.MultiPolygon; import org.elasticsearch.geometry.Point; import org.elasticsearch.geometry.Polygon; +import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.index.mapper.GeoShapeIndexer; import org.elasticsearch.test.ESTestCase; import java.io.IOException; @@ -292,6 +294,24 @@ public void testMultiPoint() { assertEquals(indexed, indexer.prepareForIndexing(multiPoint)); } + public void testRectangle() { + Rectangle indexed = new Rectangle(-179, -178, 10, -10); + Geometry processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // a rectangle is broken into two triangles + List fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 2); + + indexed = new Rectangle(179, -179, 10, -10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // a rectangle crossing the dateline is broken into 4 triangles + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 4); + } + public void testPolygon() { Polygon polygon = new Polygon(new LinearRing(new double[]{160, 200, 200, 160, 160}, new double[]{10, 10, 20, 20, 10})); Geometry indexed = new MultiPolygon(Arrays.asList( diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 032c6d68766be..eca23aba9eab0 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -791,4 +791,24 @@ public void testDistanceQuery() throws Exception { .get(); assertEquals(0, response.getHits().getTotalHits().value); } + + public void testIndexRectangleSpanningDateLine() throws Exception { + String mapping = Strings.toString(createRandomMapping()); + + client().admin().indices().prepareCreate("test").setMapping(mapping).get(); + ensureGreen(); + + EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(178, 10), new Coordinate(-178, -10)); + + XContentBuilder docSource = envelopeBuilder.toXContent(jsonBuilder().startObject().field("geo"), null).endObject(); + client().prepareIndex("test").setId("1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get(); + + ShapeBuilder filterShape = new PointBuilder(179, 0); + + GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape); + geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS); + SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get(); + assertSearchResponse(result); + assertHitCount(result, 1); + } }