Elasticsearch Geo queries - Java API

We are migrating to ES and need to support different geo queries. We use a geo_point field type in our mapping. I can see that ES supports geo_bounding_box & geo_distance but I'm trying to figure out whether they can be used for our use cases below:

1.BBOX: where the box is defined using a central point & radius. As far as I understand, the geo_distance will create a circular shape, how can we use a bbox of that circle?

//something like this - but we want a box shape not circle
        .point(lat, lon)
        .distance(r, DistanceUnit.KILOMETERS);

2.LAT_WITHIN: how can we check for documents with latitude that is within a distance (north & south) from a central latitude?

//something like this - but with only lat & radius
        .point(lat)   //only lat?
        .distance(r, DistanceUnit.KILOMETERS);

3.LON_WITHIN: similarly to the above point but for longitude.

4.SAME POINT: find documents with the same lat & lon. So can we use here the geo point field in a term query or is it possible to use the lat/lon keys?
using the first query below gives error "Geo fields do not support exact searching, use dedicated geo queries instead: [location]". The second query doesn't return results.

//point equal - this gives error
QueryBuilders.termQuery("location", "lat,lon");
//OR - this doesn't return
.must(QueryBuilders.termQuery("location.lat", lat))
.must(QueryBuilders.termQuery("location.lon", lon));


To support those use cases you will have to do some work on your side:

  1. This is currently not possible, you need to compute the bounding box on the client and then build the query.

  2. This is something similar as you can define the query as geo_bounding_box. First calculate the upper and lower bound for the latitude in the client and then generate the corresponding bounding box using -180 & 180 for the longitude.

  3. Same as above.

  4. geo points are encoded in the index with a small lost of precision (~1cm on the surface of the earth) and therefore equality is not possible. You can either filter by distance using a very small distance (~1cm) or you can index lat and Lon in another field and use that for equality.


Thanks for your reply.
Is there a util class in the lib or any external lib that would calculate this? I couldn't find any guide online.

This class in Lucene might contain most of the logic you need, in particular have a look into fromPointDistance and axisLat methods

Thanks Vera & sorry for the late reply.
I think the fromPointDistance would solve my first problem by supplying the generated Rectangle points to a geo_bounding_box query

 Rectangle rectangle = Rectangle.fromPointDistance(
            lat, lon,  DistanceUnit.convert(distance, DistanceUnit.KILOMETERS, DistanceUnit.METERS));
QueryBuilder queryBuilder = QueryBuilders.geoBoundingBoxQuery("location")
            .setCorners(rectangle.maxLat, rectangle.maxLon, rectangle.minLat, rectangle.minLon);

I tried the axisLat method with the following values

double cenLat = 14;
double distance = 225;
distance = DistanceUnit.convert(distance, DistanceUnit.KILOMETERS, DistanceUnit.METERS);
double maxLat = Rectangle.axisLat(cenLat, distance);
double minLat = ??;

// this prints 222390.1594687375
log.info("{}", GeoUtils.planeDistance(14,0,12,0));

I got maxLat value = 14.0089134. I know from an example that latitude 12 is between 220 - 230 km from latitude 14, but I don't get the expected result.
I'm probably misusing the function. can you please help.


I think we are misunderstanding what Rectangle.axisLat does. It gives you the latitude of a circle's intersections with its bbox meridians which I think it is not what you want. This is the intersection of the box with the circle at minLon and maxLon.

I think in your case you can use again the method Rectangle.fromPointDistance with a dummy longitude (e.g. 0.0) and use the given minLat and maxLat.

Thank you very much. This now gives expected values using the Rectangle.fromPointDistance.

Many thanks

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.