From 98dbe4ac006743c772711be9ceccb26c140c3ddb Mon Sep 17 00:00:00 2001 From: Evan Owen Date: Fri, 18 Oct 2013 15:02:11 -0700 Subject: [PATCH] Add support for search by Geoshape of type POLYGON The current version of ElasticSearch supports the GeoPolygonFilter, so it's trivial to add support for polygons with an arbitray number of boundary points. Signed-off-by: Evan Owen --- .../titan/core/attribute/Geoshape.java | 33 +++++++++++++++++++ .../diskstorage/es/ElasticSearchIndex.java | 7 ++++ .../indexing/IndexProviderTest.java | 4 +++ 3 files changed, 44 insertions(+) diff --git a/titan-core/src/main/java/com/thinkaurelius/titan/core/attribute/Geoshape.java b/titan-core/src/main/java/com/thinkaurelius/titan/core/attribute/Geoshape.java index b423117b5d..b178a6f6d4 100644 --- a/titan-core/src/main/java/com/thinkaurelius/titan/core/attribute/Geoshape.java +++ b/titan-core/src/main/java/com/thinkaurelius/titan/core/attribute/Geoshape.java @@ -256,6 +256,39 @@ public static final Geoshape box(final double southWestLatitude, final double so return box((float)southWestLatitude,(float)southWestLongitude,(float)northEastLatitude,(float)northEastLongitude); } + /** + * Constructs a new polygon shape which is identified by its coordinates + * @param coordinates + * @return + */ + public static final Geoshape polygon(final float ... coordinates) { + Preconditions.checkArgument(coordinates.length % 2 == 0, "Odd number of coordinates provided"); + Preconditions.checkArgument(coordinates.length >= 6, "Too few coordinate pairs provided"); + float[] latitudes = new float[coordinates.length / 2]; + float[] longitudes = new float[coordinates.length / 2]; + for (int i = 0; i < coordinates.length; i++) { + if (i % 2 == 0) { + latitudes[i / 2] = coordinates[i]; + } else { + longitudes[i / 2] = coordinates[i]; + } + } + return new Geoshape(new float[][]{ latitudes, longitudes }); + } + + /** + * Constructs a new polygon shape which is identified by its coordinates + * @param coordinates + * @return + */ + public static final Geoshape polygon(final double ... coordinates) { + float[] floatCoordinates = new float[coordinates.length]; + for (int i = 0; i < coordinates.length; i++) { + floatCoordinates[i] = (float)coordinates[i]; + } + return polygon(floatCoordinates); + } + /** * Whether the given coordinates mark a point on earth. * @param latitude diff --git a/titan-es/src/main/java/com/thinkaurelius/titan/diskstorage/es/ElasticSearchIndex.java b/titan-es/src/main/java/com/thinkaurelius/titan/diskstorage/es/ElasticSearchIndex.java index de4f587fa7..9aa13fd3e5 100644 --- a/titan-es/src/main/java/com/thinkaurelius/titan/diskstorage/es/ElasticSearchIndex.java +++ b/titan-es/src/main/java/com/thinkaurelius/titan/diskstorage/es/ElasticSearchIndex.java @@ -424,6 +424,13 @@ public FilterBuilder getFilter(Condition condition) { Geoshape.Point southwest = shape.getPoint(0); Geoshape.Point northeast = shape.getPoint(1); return FilterBuilders.geoBoundingBoxFilter(key).bottomRight(southwest.getLatitude(), northeast.getLongitude()).topLeft(northeast.getLatitude(), southwest.getLongitude()); + } else if (shape.getType() == Geoshape.Type.POLYGON) { + GeoPolygonFilterBuilder polygonFilter = FilterBuilders.geoPolygonFilter(key); + for (int i = 0; i < shape.size(); i++) { + Geoshape.Point point = shape.getPoint(i); + polygonFilter.addPoint(point.getLatitude(), point.getLongitude()); + } + return polygonFilter; } else throw new IllegalArgumentException("Unsupported or invalid search shape type: " + shape.getType()); } else throw new IllegalArgumentException("Unsupported type: " + value); diff --git a/titan-test/src/main/java/com/thinkaurelius/titan/diskstorage/indexing/IndexProviderTest.java b/titan-test/src/main/java/com/thinkaurelius/titan/diskstorage/indexing/IndexProviderTest.java index cb10e8c149..038bbed1d6 100644 --- a/titan-test/src/main/java/com/thinkaurelius/titan/diskstorage/indexing/IndexProviderTest.java +++ b/titan-test/src/main/java/com/thinkaurelius/titan/diskstorage/indexing/IndexProviderTest.java @@ -162,6 +162,10 @@ private void storeTest(String... stores) throws Exception { assertEquals(2, result.size()); assertEquals(ImmutableSet.of("doc1", "doc2"), ImmutableSet.copyOf(result)); + result = tx.query(new IndexQuery(store, PredicateCondition.of("location", Geo.WITHIN, Geoshape.polygon(48.5,0.0, 47.5,-0.5, 47.5,0.5)))); + assertEquals(1, result.size()); + assertEquals(ImmutableSet.of("doc1"), ImmutableSet.copyOf(result)); + result = tx.query(new IndexQuery(store, And.of(PredicateCondition.of("text", Text.CONTAINS, "tomorrow"), PredicateCondition.of("location", Geo.WITHIN, Geoshape.circle(48.5, 0.5, 200.00))))); assertEquals(ImmutableSet.of("doc2"), ImmutableSet.copyOf(result));