2

I'm building an application that requires elasticsearch to find the nearest location based on latitude and longitude. At the moment I'm able to do this based on a GeoPoint and a maximum distance in kilometers.

@Override
public List<CityDefinition> findCitiesNearby(GeoPoint geo, double distance, String source) {
    LOGGER.info("<findCitiesNearby>");

    FilterBuilder filterBuilderGeo = FilterBuilders.geoDistanceFilter("geo").point(geo.getLat(), geo.getLon()).distance(distance, DistanceUnit.KILOMETERS);

    SearchQuery q = new NativeSearchQueryBuilder()
            .withFilter(filterBuilderGeo);

    List<CityDefinition> fields = esOps.queryForList(q, CityDefinition.class);

    return fields;
}

This works almost perfect but instead of searching within a given distance I want elastic to return the nearest location no matter the distance. Is this possible? If it is, how do I do this?

Glenn Van Schil
  • 1,059
  • 3
  • 15
  • 33

2 Answers2

1

You could sort by distance, rather than filter.

Something along those lines should work:

public List<CityDefinition> findCitiesNearby(GeoPoint geo, double distance, String source) {
    GeoDistanceSortBuilder geoDistanceSort = SortBuilders.geoDistanceSort("geo").point(geo.lat(), geo.lon())
            .unit(DistanceUnit.KILOMETERS).sortMode("ASC")
            .geoDistance(GeoDistance.PLANE);

    final int limit = 1; // if you want only the single nearest result.
    SearchQuery q = new NativeSearchQueryBuilder()
            .withSort(geoDistanceSort)
            .withPageable(new PageRequest(0, limit))
            .build();

    List<CityDefinition> fields = esOps.queryForList(q, CityDefinition.class);

    return fields;
}
Thomas
  • 705
  • 5
  • 13
0

Apparently it's possible to just remove the distance part.

@Override
public List<CityDefinition> findCitiesNearby(GeoPoint geo, double distance, String source) {
    LOGGER.info("<findCitiesNearby>");

    //FilterBuilder filterBuilderGeo = FilterBuilders.geoDistanceFilter("geo").point(geo.getLat(), geo.getLon()).distance(distance, DistanceUnit.KILOMETERS);

    FilterBuilder filterBuilderGeo = FilterBuilders.geoDistanceFilter("geo").point(geo.getLat(), geo.getLon());

    SearchQuery q = new NativeSearchQueryBuilder()
            .withFilter(filterBuilderGeo);

    List<?> fields = esOps.queryForList(q, CityDefinition.class);

    return (List<CityDefinition>) fields;
}
Glenn Van Schil
  • 1,059
  • 3
  • 15
  • 33
  • could you share more about information how to use the elastic search with location please? How should the data will mapped in the ES? – Iman Tumorang Jan 30 '17 at 14:47
  • @ImanTumorang I thinks I'm not the right person to explain everything on how ES works with GEO related problems. What I can do is provide you some related docs: https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-point.html https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-queries.html This should get you on the right track! – Glenn Van Schil Jan 31 '17 at 09:50