Browse Source

Add support for Lucene 5.4 GeoPoint queries

This commit adds query support for Lucene 5.4 GeoPointField type along with backward compatibility for (soon to be) "legacy" geo_point indexes.
Nicholas Knize 10 years ago
parent
commit
86ae08fa88

+ 13 - 0
core/src/main/java/org/elasticsearch/common/geo/GeoUtils.java

@@ -66,6 +66,19 @@ public class GeoUtils {
     /** Earth ellipsoid polar distance in meters */
     public static final double EARTH_POLAR_DISTANCE = Math.PI * EARTH_SEMI_MINOR_AXIS;
 
+    /** Returns the maximum distance/radius from the point 'center' before overlapping */
+    public static double maxRadialDistance(GeoPoint center) {
+        return SloppyMath.haversin(center.lat(), center.lon(), center.lat(), (180.0 + center.lon()) % 360)*1000.0;
+    }
+
+    /** Returns the minimum between the provided distance 'initialRadius' and the
+     * maximum distance/radius from the point 'center' before overlapping
+     **/
+    public static double maxRadialDistance(GeoPoint center, double initialRadius) {
+        final double maxRadius = maxRadialDistance(center);
+        return Math.min(initialRadius, maxRadius);
+    }
+
     /** Returns true if latitude is actually a valid latitude value.*/
     public static boolean isValidLatitude(double latitude) {
         if (Double.isNaN(latitude) || Double.isInfinite(latitude) || latitude < GeoUtils.MIN_LAT || latitude > GeoUtils.MAX_LAT) {

+ 10 - 4
core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.index.query;
 
+import org.apache.lucene.search.GeoPointInBBoxQuery;
 import org.apache.lucene.search.Query;
 import org.elasticsearch.Version;
 import org.elasticsearch.common.Numbers;
@@ -263,21 +264,26 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilder<GeoBounding
         }
         GeoPointFieldMapper.GeoPointFieldType geoFieldType = ((GeoPointFieldMapper.GeoPointFieldType) fieldType);
 
-        Query result;
+        // norelease cut over to .before(Version.2_2_0) once GeoPointFieldV2 is fully merged
+        if (context.indexVersionCreated().after(Version.CURRENT)) {
+            return new GeoPointInBBoxQuery(fieldType.names().fullName(), topLeft.lon(), bottomRight.lat(), bottomRight.lon(), topLeft.lat());
+        }
+
+        Query query;
         switch(type) {
             case INDEXED:
-                result = IndexedGeoBoundingBoxQuery.create(luceneTopLeft, luceneBottomRight, geoFieldType);
+                query = IndexedGeoBoundingBoxQuery.create(luceneTopLeft, luceneBottomRight, geoFieldType);
                 break;
             case MEMORY:
                 IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
-                result = new InMemoryGeoBoundingBoxQuery(luceneTopLeft, luceneBottomRight, indexFieldData);
+                query = new InMemoryGeoBoundingBoxQuery(luceneTopLeft, luceneBottomRight, indexFieldData);
                 break;
             default:
                 // Someone extended the type enum w/o adjusting this switch statement.
                 throw new IllegalStateException("geo bounding box type [" + type + "] not supported.");
         }
 
-        return result;
+        return query;
     }
 
     @Override

+ 10 - 4
core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.index.query;
 
+import org.apache.lucene.search.GeoPointDistanceQuery;
 import org.apache.lucene.search.Query;
 import org.elasticsearch.Version;
 import org.elasticsearch.common.Strings;
@@ -221,11 +222,16 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue
         if (!(fieldType instanceof GeoPointFieldMapper.GeoPointFieldType)) {
             throw new QueryShardException(shardContext, "field [" + fieldName + "] is not a geo_point field");
         }
-        GeoPointFieldMapper.GeoPointFieldType geoFieldType = ((GeoPointFieldMapper.GeoPointFieldType) fieldType);
 
-        IndexGeoPointFieldData indexFieldData = shardContext.getForField(fieldType);
-        Query query = new GeoDistanceRangeQuery(center, null, normDistance, true, false, geoDistance, geoFieldType, indexFieldData, optimizeBbox);
-        return query;
+        // norelease cut over to .before(Version.2_2_0) once GeoPointFieldV2 is fully merged
+        if (shardContext.indexVersionCreated().onOrBefore(Version.CURRENT)) {
+            GeoPointFieldMapper.GeoPointFieldType geoFieldType = ((GeoPointFieldMapper.GeoPointFieldType) fieldType);
+            IndexGeoPointFieldData indexFieldData = shardContext.getForField(fieldType);
+            return new GeoDistanceRangeQuery(center, null, normDistance, true, false, geoDistance, geoFieldType, indexFieldData, optimizeBbox);
+        }
+
+        normDistance = GeoUtils.maxRadialDistance(center, normDistance);
+        return new GeoPointDistanceQuery(fieldType.names().fullName(), center.lon(), center.lat(), normDistance);
     }
 
     @Override

+ 19 - 4
core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.index.query;
 
+import org.apache.lucene.search.GeoPointDistanceRangeQuery;
 import org.apache.lucene.search.Query;
 import org.elasticsearch.Version;
 import org.elasticsearch.common.Strings;
@@ -38,6 +39,8 @@ import java.io.IOException;
 import java.util.Locale;
 import java.util.Objects;
 
+import static org.apache.lucene.util.GeoUtils.TOLERANCE;
+
 public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistanceRangeQueryBuilder> {
 
     public static final String NAME = "geo_distance_range";
@@ -235,7 +238,10 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
                 fromValue = DistanceUnit.parse((String) from, unit, DistanceUnit.DEFAULT);
             }
             fromValue = geoDistance.normalize(fromValue, DistanceUnit.DEFAULT);
+        } else {
+            fromValue = new Double(0);
         }
+
         if (to != null) {
             if (to instanceof Number) {
                 toValue = unit.toMeters(((Number) to).doubleValue());
@@ -243,6 +249,8 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
                 toValue = DistanceUnit.parse((String) to, unit, DistanceUnit.DEFAULT);
             }
             toValue = geoDistance.normalize(toValue, DistanceUnit.DEFAULT);
+        } else {
+            toValue = GeoUtils.maxRadialDistance(point);
         }
 
         MappedFieldType fieldType = context.fieldMapper(fieldName);
@@ -252,11 +260,18 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan
         if (!(fieldType instanceof GeoPointFieldMapper.GeoPointFieldType)) {
             throw new QueryShardException(context, "field [" + fieldName + "] is not a geo_point field");
         }
-        GeoPointFieldMapper.GeoPointFieldType geoFieldType = ((GeoPointFieldMapper.GeoPointFieldType) fieldType);
 
-        IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
-        return new GeoDistanceRangeQuery(point, fromValue, toValue, includeLower, includeUpper, geoDistance, geoFieldType,
-                indexFieldData, optimizeBbox);
+        // norelease cut over to .before(Version.2_2_0) once GeoPointFieldV2 is fully merged
+        if (context.indexVersionCreated().onOrBefore(Version.CURRENT)) {
+            GeoPointFieldMapper.GeoPointFieldType geoFieldType = ((GeoPointFieldMapper.GeoPointFieldType) fieldType);
+            IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
+            return new GeoDistanceRangeQuery(point, fromValue, toValue, includeLower, includeUpper, geoDistance, geoFieldType,
+                    indexFieldData, optimizeBbox);
+        }
+
+        return new GeoPointDistanceRangeQuery(fieldType.names().fullName(), point.lon(), point.lat(),
+                (includeLower) ? fromValue : fromValue + TOLERANCE,
+                (includeUpper) ? toValue : toValue - TOLERANCE);
     }
 
     @Override

+ 17 - 2
core/src/main/java/org/elasticsearch/index/query/GeoPolygonQueryBuilder.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.index.query;
 
+import org.apache.lucene.search.GeoPointInPolygonQuery;
 import org.apache.lucene.search.Query;
 import org.elasticsearch.Version;
 import org.elasticsearch.common.Strings;
@@ -104,6 +105,7 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
         for (GeoPoint geoPoint : this.shell) {
             shell.add(new GeoPoint(geoPoint));
         }
+        final int shellSize = shell.size();
 
         final boolean indexCreatedBeforeV2_0 = context.indexVersionCreated().before(Version.V_2_0_0);
         // validation was not available prior to 2.x, so to support bwc
@@ -135,8 +137,21 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery
             throw new QueryShardException(context, "field [" + fieldName + "] is not a geo_point field");
         }
 
-        IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
-        return new GeoPolygonQuery(indexFieldData, shell.toArray(new GeoPoint[shell.size()]));
+        // norelease cut over to .before(Version.2_2_0) once GeoPointFieldV2 is fully merged
+        if (context.indexVersionCreated().onOrBefore(Version.CURRENT)) {
+            IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
+            return new GeoPolygonQuery(indexFieldData, shell.toArray(new GeoPoint[shellSize]));
+        }
+
+        double[] lats = new double[shellSize];
+        double[] lons = new double[shellSize];
+        GeoPoint p;
+        for (int i=0; i<shellSize; ++i) {
+            p = new GeoPoint(shell.get(i));
+            lats[i] = p.lat();
+            lons[i] = p.lon();
+        }
+        return new GeoPointInPolygonQuery(fieldType.names().fullName(), lons, lats);
     }
 
     @Override

+ 21 - 11
core/src/test/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilderTests.java

@@ -22,14 +22,14 @@ package org.elasticsearch.index.query;
 import com.spatial4j.core.io.GeohashUtils;
 import com.spatial4j.core.shape.Rectangle;
 
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ConstantScoreQuery;
-import org.apache.lucene.search.NumericRangeQuery;
-import org.apache.lucene.search.Query;
+import org.apache.lucene.search.*;
+import org.elasticsearch.Version;
+import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.geo.GeoUtils;
+import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.index.search.geo.InMemoryGeoBoundingBoxQuery;
+import org.elasticsearch.test.VersionUtils;
 import org.elasticsearch.test.geo.RandomShapeGenerator;
 
 import java.io.IOException;
@@ -423,11 +423,21 @@ public class GeoBoundingBoxQueryBuilderTests extends AbstractQueryTestCase<GeoBo
 
     private void assertGeoBoundingBoxQuery(String query) throws IOException {
         Query parsedQuery = parseQuery(query).toQuery(createShardContext());
-        InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) parsedQuery;
-        assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
-        assertThat(filter.topLeft().lat(), closeTo(40, 0.00001));
-        assertThat(filter.topLeft().lon(), closeTo(-70, 0.00001));
-        assertThat(filter.bottomRight().lat(), closeTo(30, 0.00001));
-        assertThat(filter.bottomRight().lon(), closeTo(-80, 0.00001));
+        // norelease cut over to .before(Version.2_2_0) once GeoPointFieldV2 is fully merged
+        if (queryShardContext().indexVersionCreated().onOrBefore(Version.CURRENT)) {
+            InMemoryGeoBoundingBoxQuery filter = (InMemoryGeoBoundingBoxQuery) parsedQuery;
+            assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
+            assertThat(filter.topLeft().lat(), closeTo(40, 1E-5));
+            assertThat(filter.topLeft().lon(), closeTo(-70, 1E-5));
+            assertThat(filter.bottomRight().lat(), closeTo(30, 1E-5));
+            assertThat(filter.bottomRight().lon(), closeTo(-80, 1E-5));
+        } else {
+            GeoPointInBBoxQuery q = (GeoPointInBBoxQuery) parsedQuery;
+            assertThat(q.getField(), equalTo(GEO_POINT_FIELD_NAME));
+            assertThat(q.getMaxLat(), closeTo(40, 1E-5));
+            assertThat(q.getMinLon(), closeTo(-70, 1E-5));
+            assertThat(q.getMinLat(), closeTo(30, 1E-5));
+            assertThat(q.getMaxLon(), closeTo(-80, 1E-5));
+        }
     }
 }

+ 58 - 32
core/src/test/java/org/elasticsearch/index/query/GeoDistanceQueryBuilderTests.java

@@ -21,7 +21,10 @@ package org.elasticsearch.index.query;
 
 import com.spatial4j.core.shape.Point;
 
+import org.apache.lucene.search.GeoPointDistanceQuery;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.util.GeoUtils;
+import org.elasticsearch.Version;
 import org.elasticsearch.common.geo.GeoDistance;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.unit.DistanceUnit;
@@ -158,6 +161,16 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
 
     @Override
     protected void doAssertLuceneQuery(GeoDistanceQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
+        Version version = context.indexVersionCreated();
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (version.onOrBefore(Version.CURRENT)) {
+            assertLegacyQuery(queryBuilder, query);
+        } else {
+            assertGeoPointQuery(queryBuilder, query);
+        }
+    }
+
+    private void assertLegacyQuery(GeoDistanceQueryBuilder queryBuilder, Query query) throws IOException {
         assertThat(query, instanceOf(GeoDistanceRangeQuery.class));
         GeoDistanceRangeQuery geoQuery = (GeoDistanceRangeQuery) query;
         assertThat(geoQuery.fieldName(), equalTo(queryBuilder.fieldName()));
@@ -169,11 +182,26 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
         assertThat(geoQuery.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
         double distance = queryBuilder.distance();
         if (queryBuilder.geoDistance() != null) {
-                distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT);
+            distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT);
         }
         assertThat(geoQuery.maxInclusiveDistance(), closeTo(distance, Math.abs(distance) / 1000));
     }
 
+    private void assertGeoPointQuery(GeoDistanceQueryBuilder queryBuilder, Query query) throws IOException {
+        assertThat(query, instanceOf(GeoPointDistanceQuery.class));
+        GeoPointDistanceQuery geoQuery = (GeoPointDistanceQuery) query;
+        assertThat(geoQuery.getField(), equalTo(queryBuilder.fieldName()));
+        if (queryBuilder.point() != null) {
+            assertThat(geoQuery.getCenterLat(), equalTo(queryBuilder.point().lat()));
+            assertThat(geoQuery.getCenterLon(), equalTo(queryBuilder.point().lon()));
+        }
+        double distance = queryBuilder.distance();
+        if (queryBuilder.geoDistance() != null) {
+            distance = queryBuilder.geoDistance().normalize(distance, DistanceUnit.DEFAULT);
+            assertThat(geoQuery.getRadiusMeters(), closeTo(distance, GeoUtils.TOLERANCE));
+        }
+    }
+
     public void testParsingAndToQuery1() throws IOException {
         assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
         String query = "{\n" +
@@ -185,7 +213,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery2() throws IOException {
@@ -196,7 +224,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        \"" + GEO_POINT_FIELD_NAME + "\":[-70, 40]\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery3() throws IOException {
@@ -207,7 +235,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        \"" + GEO_POINT_FIELD_NAME + "\":\"40, -70\"\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery4() throws IOException {
@@ -218,7 +246,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        \"" + GEO_POINT_FIELD_NAME + "\":\"drn5x1g8cu2y\"\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery5() throws IOException {
@@ -233,7 +261,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery6() throws IOException {
@@ -248,7 +276,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery7() throws IOException {
@@ -262,13 +290,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "      }\n" +
                 "  }\n" +
                 "}\n";
-        Query parsedQuery = parseQuery(query).toQuery(createShardContext());
-        GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) parsedQuery;
-        assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
-        assertThat(filter.lat(), closeTo(40, 0.00001));
-        assertThat(filter.lon(), closeTo(-70, 0.00001));
-        assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
-        assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(0.012, DistanceUnit.MILES), 0.00001));
+        assertGeoDistanceRangeQuery(query, 40, -70, 0.012, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery8() throws IOException {
@@ -282,13 +304,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        Query parsedQuery = parseQuery(query).toQuery(createShardContext());
-        GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) parsedQuery;
-        assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
-        assertThat(filter.lat(), closeTo(40, 0.00001));
-        assertThat(filter.lon(), closeTo(-70, 0.00001));
-        assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
-        assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.KILOMETERS.convert(12, DistanceUnit.MILES), 0.00001));
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.KILOMETERS);
     }
 
     public void testParsingAndToQuery9() throws IOException {
@@ -303,7 +319,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery10() throws IOException {
@@ -318,7 +334,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery11() throws IOException {
@@ -332,7 +348,7 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
     public void testParsingAndToQuery12() throws IOException {
@@ -347,17 +363,27 @@ public class GeoDistanceQueryBuilderTests extends AbstractQueryTestCase<GeoDista
                 "        }\n" +
                 "    }\n" +
                 "}\n";
-        assertGeoDistanceRangeQuery(query);
+        assertGeoDistanceRangeQuery(query, 40, -70, 12, DistanceUnit.DEFAULT);
     }
 
-    private void assertGeoDistanceRangeQuery(String query) throws IOException {
+    private void assertGeoDistanceRangeQuery(String query, double lat, double lon, double distance, DistanceUnit distanceUnit) throws IOException {
         assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
         Query parsedQuery = parseQuery(query).toQuery(createShardContext());
-        GeoDistanceRangeQuery filter = (GeoDistanceRangeQuery) parsedQuery;
-        assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
-        assertThat(filter.lat(), closeTo(40, 0.00001));
-        assertThat(filter.lon(), closeTo(-70, 0.00001));
-        assertThat(filter.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
-        assertThat(filter.maxInclusiveDistance(), closeTo(DistanceUnit.DEFAULT.convert(12, DistanceUnit.MILES), 0.00001));
+        Version version = queryShardContext().indexVersionCreated();
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (version.onOrBefore(Version.CURRENT)) {
+            GeoDistanceRangeQuery q = (GeoDistanceRangeQuery) parsedQuery;
+            assertThat(q.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
+            assertThat(q.lat(), closeTo(lat, 1E-5D));
+            assertThat(q.lon(), closeTo(lon, 1E-5D));
+            assertThat(q.minInclusiveDistance(), equalTo(Double.NEGATIVE_INFINITY));
+            assertThat(q.maxInclusiveDistance(), closeTo(distanceUnit.convert(distance, DistanceUnit.MILES), 1E-5D));
+        } else {
+            GeoPointDistanceQuery q = (GeoPointDistanceQuery) parsedQuery;
+            assertThat(q.getField(), equalTo(GEO_POINT_FIELD_NAME));
+            assertThat(q.getCenterLat(), closeTo(lat, 1E-5D));
+            assertThat(q.getCenterLon(), closeTo(lon, 1E-5D));
+            assertThat(q.getRadiusMeters(), closeTo(distanceUnit.convert(distance, DistanceUnit.MILES), 1E-5D));
+        }
     }
 }

+ 66 - 14
core/src/test/java/org/elasticsearch/index/query/GeoDistanceRangeQueryTests.java

@@ -19,7 +19,10 @@
 
 package org.elasticsearch.index.query;
 
+import org.apache.lucene.search.GeoPointDistanceRangeQuery;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.util.SloppyMath;
+import org.elasticsearch.Version;
 import org.elasticsearch.common.geo.GeoDistance;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.geo.GeoUtils;
@@ -37,6 +40,7 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
 
     @Override
     protected GeoDistanceRangeQueryBuilder doCreateTestQueryBuilder() {
+        Version version = queryShardContext().indexVersionCreated();
         GeoDistanceRangeQueryBuilder builder;
         if (randomBoolean()) {
             builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, randomGeohash(1, 12));
@@ -49,35 +53,45 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
                 builder = new GeoDistanceRangeQueryBuilder(GEO_POINT_FIELD_NAME, lat, lon);
             }
         }
-        int fromValue = randomInt(1000000);
-        int toValue = randomIntBetween(fromValue, 1000000);
-        String fromToUnits = randomFrom(DistanceUnit.values()).toString();
+        GeoPoint point = builder.point();
+        // todo remove the following pole hack when LUCENE-6846 lands
+        final double distToPole = SloppyMath.haversin(point.lat(), point.lon(), (point.lat()<0) ? -90.0 : 90.0, point.lon());
+        final double maxRadius = GeoUtils.maxRadialDistance(point, distToPole);
+
+        final int fromValueMeters = randomInt((int)(maxRadius*0.5));
+        final int toValueMeters = randomIntBetween(fromValueMeters, (int)maxRadius);
+        DistanceUnit fromToUnits = randomFrom(DistanceUnit.values());
+        final String fromToUnitsStr = fromToUnits.toString();
+        final double fromValue = DistanceUnit.convert(fromValueMeters, DistanceUnit.DEFAULT, fromToUnits);
+        final double toValue = DistanceUnit.convert(toValueMeters, DistanceUnit.DEFAULT, fromToUnits);
+
         if (randomBoolean()) {
             int branch = randomInt(2);
+            fromToUnits = DistanceUnit.DEFAULT;
             switch (branch) {
             case 0:
-                builder.from(fromValue);
+                builder.from(fromValueMeters);
                 break;
             case 1:
                 builder.to(toValue);
                 break;
             case 2:
-                builder.from(fromValue);
-                builder.to(toValue);
+                builder.from(fromValueMeters);
+                builder.to(toValueMeters);
                 break;
             }
         } else {
             int branch = randomInt(2);
             switch (branch) {
             case 0:
-                builder.from(fromValue + fromToUnits);
+                builder.from(fromValue + fromToUnitsStr);
                 break;
             case 1:
-                builder.to(toValue + fromToUnits);
+                builder.to(toValue + fromToUnitsStr);
                 break;
             case 2:
-                builder.from(fromValue + fromToUnits);
-                builder.to(toValue + fromToUnits);
+                builder.from(fromValue + fromToUnitsStr);
+                builder.to(toValue + fromToUnitsStr);
                 break;
             }
         }
@@ -90,12 +104,11 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
         if (randomBoolean()) {
             builder.geoDistance(randomFrom(GeoDistance.values()));
         }
-        if (randomBoolean()) {
-            builder.unit(randomFrom(DistanceUnit.values()));
-        }
-        if (randomBoolean()) {
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (randomBoolean() && version.onOrBefore(Version.CURRENT)) {
             builder.optimizeBbox(randomFrom("none", "memory", "indexed"));
         }
+        builder.unit(fromToUnits);
         if (randomBoolean()) {
             builder.setValidationMethod(randomFrom(GeoValidationMethod.values()));
         }
@@ -105,6 +118,16 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
     @Override
     protected void doAssertLuceneQuery(GeoDistanceRangeQueryBuilder queryBuilder, Query query, QueryShardContext context)
             throws IOException {
+        Version version = context.indexVersionCreated();
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (version.onOrBefore(Version.CURRENT)) {
+            assertLegacyQuery(queryBuilder, query);
+        } else {
+            assertGeoPointQuery(queryBuilder, query);
+        }
+    }
+
+    private void assertLegacyQuery(GeoDistanceRangeQueryBuilder queryBuilder, Query query) throws IOException {
         assertThat(query, instanceOf(GeoDistanceRangeQuery.class));
         GeoDistanceRangeQuery geoQuery = (GeoDistanceRangeQuery) query;
         assertThat(geoQuery.fieldName(), equalTo(queryBuilder.fieldName()));
@@ -139,6 +162,35 @@ public class GeoDistanceRangeQueryTests extends AbstractQueryTestCase<GeoDistanc
         }
     }
 
+    private void assertGeoPointQuery(GeoDistanceRangeQueryBuilder queryBuilder, Query query) throws IOException {
+        assertThat(query, instanceOf(GeoPointDistanceRangeQuery.class));
+        GeoPointDistanceRangeQuery geoQuery = (GeoPointDistanceRangeQuery) query;
+        assertThat(geoQuery.getField(), equalTo(queryBuilder.fieldName()));
+        if (queryBuilder.point() != null) {
+            GeoPoint expectedPoint = new GeoPoint(queryBuilder.point());
+            GeoUtils.normalizePoint(expectedPoint);
+            assertThat(geoQuery.getCenterLat(), equalTo(expectedPoint.lat()));
+            assertThat(geoQuery.getCenterLon(), equalTo(expectedPoint.lon()));
+        }
+        if (queryBuilder.from() != null && queryBuilder.from() instanceof Number) {
+            double fromValue = ((Number) queryBuilder.from()).doubleValue();
+            if (queryBuilder.unit() != null) {
+                fromValue = queryBuilder.unit().toMeters(fromValue);
+            }
+            assertThat(geoQuery.getMinRadiusMeters(), closeTo(fromValue, 1E-5));
+        }
+        if (queryBuilder.to() != null && queryBuilder.to() instanceof Number) {
+            double toValue = ((Number) queryBuilder.to()).doubleValue();
+            if (queryBuilder.unit() != null) {
+                toValue = queryBuilder.unit().toMeters(toValue);
+            }
+            if (queryBuilder.geoDistance() != null) {
+                toValue = queryBuilder.geoDistance().normalize(toValue, DistanceUnit.DEFAULT);
+            }
+            assertThat(geoQuery.getMaxRadiusMeters(), closeTo(toValue, 1E-5));
+        }
+    }
+
     /**
      * Overridden here to ensure the test is only run if at least one type is
      * present in the mappings. Geo queries do not execute if the field is not

+ 60 - 10
core/src/test/java/org/elasticsearch/index/query/GeoPolygonQueryBuilderTests.java

@@ -22,7 +22,9 @@ package org.elasticsearch.index.query;
 import com.spatial4j.core.shape.jts.JtsGeometry;
 import com.vividsolutions.jts.geom.Coordinate;
 
+import org.apache.lucene.search.GeoPointInPolygonQuery;
 import org.apache.lucene.search.Query;
+import org.elasticsearch.Version;
 import org.elasticsearch.common.ParsingException;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.geo.GeoUtils;
@@ -56,6 +58,16 @@ public class GeoPolygonQueryBuilderTests extends AbstractQueryTestCase<GeoPolygo
 
     @Override
     protected void doAssertLuceneQuery(GeoPolygonQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
+        Version version = context.indexVersionCreated();
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (version.onOrBefore(Version.CURRENT)) {
+            assertLegacyQuery(queryBuilder, query);
+        } else {
+            assertGeoPointQuery(queryBuilder, query);
+        }
+    }
+
+    private void assertLegacyQuery(GeoPolygonQueryBuilder queryBuilder, Query query) {
         assertThat(query, instanceOf(GeoPolygonQuery.class));
         GeoPolygonQuery geoQuery = (GeoPolygonQuery) query;
         assertThat(geoQuery.fieldName(), equalTo(queryBuilder.fieldName()));
@@ -76,6 +88,24 @@ public class GeoPolygonQueryBuilderTests extends AbstractQueryTestCase<GeoPolygo
         }
     }
 
+    private void assertGeoPointQuery(GeoPolygonQueryBuilder queryBuilder, Query query) {
+        assertThat(query, instanceOf(GeoPointInPolygonQuery.class));
+        GeoPointInPolygonQuery geoQuery = (GeoPointInPolygonQuery) query;
+        assertThat(geoQuery.getField(), equalTo(queryBuilder.fieldName()));
+        List<GeoPoint> queryBuilderPoints = queryBuilder.points();
+        double[] lats = geoQuery.getLats();
+        double[] lons = geoQuery.getLons();
+        assertThat(lats.length, equalTo(queryBuilderPoints.size()));
+        assertThat(lons.length, equalTo(queryBuilderPoints.size()));
+        for (int i=0; i < queryBuilderPoints.size(); ++i) {
+            final GeoPoint queryBuilderPoint = queryBuilderPoints.get(i);
+            final GeoPoint pointCopy = new GeoPoint(queryBuilderPoint);
+            GeoUtils.normalizePoint(pointCopy);
+            assertThat(lats[i], closeTo(pointCopy.getLat(), 1E-5D));
+            assertThat(lons[i], closeTo(pointCopy.getLon(), 1E-5D));
+        }
+    }
+
     /**
      * Overridden here to ensure the test is only run if at least one type is
      * present in the mappings. Geo queries do not execute if the field is not
@@ -267,15 +297,35 @@ public class GeoPolygonQueryBuilderTests extends AbstractQueryTestCase<GeoPolygo
     }
 
     private void assertGeoPolygonQuery(String query) throws IOException {
-        Query parsedQuery = parseQuery(query).toQuery(createShardContext());
-        GeoPolygonQuery filter = (GeoPolygonQuery) parsedQuery;
-        assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
-        assertThat(filter.points().length, equalTo(4));
-        assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
-        assertThat(filter.points()[0].lon(), closeTo(-70, 0.00001));
-        assertThat(filter.points()[1].lat(), closeTo(30, 0.00001));
-        assertThat(filter.points()[1].lon(), closeTo(-80, 0.00001));
-        assertThat(filter.points()[2].lat(), closeTo(20, 0.00001));
-        assertThat(filter.points()[2].lon(), closeTo(-90, 0.00001));
+        QueryShardContext context = createShardContext();
+        Version version = context.indexVersionCreated();
+        Query parsedQuery = parseQuery(query).toQuery(context);
+        // norelease update to .before(Version.V_2_2_0 once GeoPointFieldV2 is fully merged
+        if (version.onOrBefore(Version.CURRENT)) {
+            GeoPolygonQuery filter = (GeoPolygonQuery) parsedQuery;
+            assertThat(filter.fieldName(), equalTo(GEO_POINT_FIELD_NAME));
+            assertThat(filter.points().length, equalTo(4));
+            assertThat(filter.points()[0].lat(), closeTo(40, 0.00001));
+            assertThat(filter.points()[0].lon(), closeTo(-70, 0.00001));
+            assertThat(filter.points()[1].lat(), closeTo(30, 0.00001));
+            assertThat(filter.points()[1].lon(), closeTo(-80, 0.00001));
+            assertThat(filter.points()[2].lat(), closeTo(20, 0.00001));
+            assertThat(filter.points()[2].lon(), closeTo(-90, 0.00001));
+        } else {
+            GeoPointInPolygonQuery q = (GeoPointInPolygonQuery) parsedQuery;
+            assertThat(q.getField(), equalTo(GEO_POINT_FIELD_NAME));
+            final double[] lats = q.getLats();
+            final double[] lons = q.getLons();
+            assertThat(lats.length, equalTo(4));
+            assertThat(lons.length, equalTo(4));
+            assertThat(lats[0], closeTo(40, 1E-5));
+            assertThat(lons[0], closeTo(-70, 1E-5));
+            assertThat(lats[1], closeTo(30, 1E-5));
+            assertThat(lons[1], closeTo(-80, 1E-5));
+            assertThat(lats[2], closeTo(20, 1E-5));
+            assertThat(lons[2], closeTo(-90, 1E-5));
+            assertThat(lats[3], equalTo(lats[0]));
+            assertThat(lons[3], equalTo(lons[0]));
+        }
     }
 }