Given a Geo location point I am trying to find some sites within 10 Km and sort it by the nearest to the location given.
I managed to return the list of locations within 10km but when I try to sort it I get exceptions:
I am using the following versions of:
<properties>
<commonscollections>3.2.1</commonscollections>
<commonslang>2.6</commonslang>
<spring.data.elasticsearch>1.0.0.BUILD-SNAPSHOT</spring.data.elasticsearch>
<springversion>3.2.5.RELEASE</springversion>
</properties>
The java code as follow:
public List<SiteResource> findByGeoLocation(Double longitude, Double latitude, String channelKey, String distance) {
if(StringUtils.isEmpty(distance)){
distance = defaultRadius;
}
GeoPoint location = new GeoPoint(latitude, longitude);
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("location").within(location, distance+"km"));
criteriaQuery.addIndices(channelKey);
criteriaQuery.addTypes("site");
criteriaQuery.addSort(new Sort(Sort.Direction.ASC, "location"));
List<SiteResource> sites = esTemplate.queryForList(criteriaQuery, com.company.domain.site.SiteResource.class);
return sites;
}
If I remove the line:
criteriaQuery.addSort(new Sort(Sort.Direction.ASC, "location"));
then the code will returns all the locations, the problem is with the sorting
The error I am getting from elasticsearch log:
[2014-03-20 13:37:02,720][DEBUG][action.search.type ] [Smuggler II] [210a9696a28545f2bbeecf88d64fbad8_20140318_153743][4], node[dB9dCIXMRZGmdUExquMWlQ], [P], s[STARTED]: Failed to execute [org.elasticsearch.action.search.SearchRequest@71b978fe] lastShard [true]
org.elasticsearch.search.SearchParseException: [210a9696a28545f2bbeecf88d64fbad8_20140318_153743][4]: query[ConstantScore(*:*)],from[0],size[-1]: Parse Failure [Failed to parse source [{"from":0,"query":{"match_all":{}},"post_filter":{"geo_distance":{"location":[-2.217753,53.432703],"distance":"10km"}},"sort":[{"location":{"order":"asc"}}]}]]
at org.elasticsearch.search.SearchService.parseSource(SearchService.java:595)
at org.elasticsearch.search.SearchService.createContext(SearchService.java:498)
at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:472)
at org.elasticsearch.search.SearchService.executeDfsPhase(SearchService.java:178)
at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteDfs(SearchServiceTransportAction.java:168)
at org.elasticsearch.action.search.type.TransportSearchDfsQueryThenFetchAction$AsyncAction.sendExecuteFirstPhase(TransportSearchDfsQueryThenFetchAction.java:85)
at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:216)
at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.java:203)
at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$2.run(TransportSearchTypeAction.java:186)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:701)
Caused by: org.elasticsearch.ElasticsearchIllegalArgumentException: can't sort on geo_point field without using specific sorting feature, like geo_distance
at org.elasticsearch.index.fielddata.plain.AbstractGeoPointIndexFieldData.comparatorSource(AbstractGeoPointIndexFieldData.java:142)
at org.elasticsearch.search.sort.SortParseElement.addSortField(SortParseElement.java:222)
at org.elasticsearch.search.sort.SortParseElement.addCompoundSortField(SortParseElement.java:172)
at org.elasticsearch.search.sort.SortParseElement.parse(SortParseElement.java:80)
at org.elasticsearch.search.SearchService.parseSource(SearchService.java:583)
... 11 more
[2014-03-20 13:37:02,722][DEBUG][action.search.type ] [Smuggler II] All shards failed for phase: [dfs]
If someone tell me if it is possible to sort the locations by nearest to me I very much appreciate it.
Many Thanks in advance
This is becoming even more relevant with new browsers supporting Geolocation API. Already in master (and in the upcoming 0.9.1 release), elasticsearch comes with rich support for geo location. Lets take a drive down the geo support path:
The code is passing along a lat/lon point to Elasticsearch, and a geo_distance is being calculated between that point and every other point in all the documents in the index. If there are a large number of documents, then the time to compute geo_distances on all of them becomes non-trivial.
There is now a new _geo_distance sort type allowing to sort based on a distance from a specific location: On top of that, elasticsearch will now return all the values per hit of fields sorted on, allowing to easily display this important information.
Elasticsearch is much more than just a search engine: it’s also a powerful analytics tool. One of the awesome things that Elasticsearch provides out of the box is the ability to calculate the distance between geographic points, and order the results by proximity.
Just in case someone else having the same problem we have solved our sorting problem in the following way:
public List<SiteResource> findByGeoLocation(Double longitude, Double latitude, String channelKey, Double distance) {
if(StringUtils.isEmpty(distance)){
distance = defaultRadius;
}
GeoDistanceFilterBuilder filter = FilterBuilders.geoDistanceFilter("location").point(latitude, longitude).distance(distance, DistanceUnit.KILOMETERS);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withFilter(filter)
.withSort(SortBuilders.geoDistanceSort("site.location").point(latitude, longitude).order(SortOrder.ASC)).build();
searchQuery.addIndices(channelKey);
searchQuery.addTypes("site");
List<SiteResource> sites = esTemplate.queryForList(searchQuery, com.company.domain.site.SiteResource.class);
return sites;
}
Hope it help someone ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With