我已根据其位置在Elasticsearch中实现了对用户的搜索和排序。它曾经在Elasticsearch 1.6中运行良好,但在升级到Elasticsearch 2.3.3之后它就停止了工作。
这是我在ES中的映射:
{
"user": {
"properties": {
"id": {
"store": false,
"type": "long"
},
"url": {
"store": false,
"type": "string"
},
"name": {
"store": false,
"type": "string"
},
"lastname": {
"store": false,
"type": "string"
},
"system": {
"store": false,
"type": "boolean"
},
"avatar": {
"store": false,
"type": "string"
},
"position": {
"store": false,
"type": "string"
},
"location": {
"type": "geo_point"
},
"roles": {
"properties": {
"id": {
"store": false,
"type": "long"
}
}
},
"credentials": {
"type": "nested",
"properties": {
"id": {
"store": false,
"type": "long"
},
"progress": {
"store": false,
"type": "integer"
},
"instructorId": {
"store": false,
"type": "long"
},
"dateEnrolled":{
"store": false,
"type":"date",
"format":"yyyy/MM/dd HH:mm:ss"
}
}
},
"credentialsWithInstructorRole": {
"properties": {
"id": {
"store": false,
"type": "long"
},
"dateAssigned":{
"store": false,
"type":"date",
"format":"yyyy/MM/dd HH:mm:ss"
}
}
}
}
}
}
当我尝试直接执行以下查询时,它可以正常工作:
[
{
"from": 0,
"size": 3,
"query": {
"bool": {
"must_not": {
"term": {
"id": 2
}
},
"should": {
"match_all": {}
}
}
},
"sort": [
{
"_geo_distance": {
"user.location": [
{
"lat": 49.2827291,
"lon": -123.12073750000002
}
],
"unit": "km"
}
}
]
}
]
但是,使用Java API执行相同的查询时,会出现异常:
Failed to execute phase [query], all shards failed; shardFailures {[G88txaRXQESUgytUEnTwug][users_zj][0]: RemoteTransportException[[Living Colossus][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: SearchParseException[failed to parse search source [{"from":0,"size":3,"query":{"bool":{"must_not":{"term":{"id":2}},"should":{"match_all":{}}}},"sort":[{"_geo_distance":{"user.location":[{"lat":49.2827291,"lon":-123.12073750000002}],"unit":"km"}}]}]]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort]; }{[G88txaRXQESUgytUEnTwug][users_zj][1]: RemoteTransportException[[Living Colossus][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: SearchParseException[failed to parse search source [{"from":0,"size":3,"query":{"bool":{"must_not":{"term":{"id":2}},"should":{"match_all":{}}}},"sort":[{"_geo_distance":{"user.location":[{"lat":49.2827291,"lon":-123.12073750000002}],"unit":"km"}}]}]]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort]; }{[G88txaRXQESUgytUEnTwug][users_zj][2]: RemoteTransportException[[Living Colossus][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: SearchParseException[failed to parse search source [{"from":0,"size":3,"query":{"bool":{"must_not":{"term":{"id":2}},"should":{"match_all":{}}}},"sort":[{"_geo_distance":{"user.location":[{"lat":49.2827291,"lon":-123.12073750000002}],"unit":"km"}}]}]]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort]; }{[G88txaRXQESUgytUEnTwug][users_zj][3]: RemoteTransportException[[Living Colossus][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: SearchParseException[failed to parse search source [{"from":0,"size":3,"query":{"bool":{"must_not":{"term":{"id":2}},"should":{"match_all":{}}}},"sort":[{"_geo_distance":{"user.location":[{"lat":49.2827291,"lon":-123.12073750000002}],"unit":"km"}}]}]]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort]; }{[G88txaRXQESUgytUEnTwug][users_zj][4]: RemoteTransportException[[Living Colossus][127.0.0.1:9300][indices:data/read/search[phase/query]]]; nested: SearchParseException[failed to parse search source [{"from":0,"size":3,"query":{"bool":{"must_not":{"term":{"id":2}},"should":{"match_all":{}}}},"sort":[{"_geo_distance":{"user.location":[{"lat":49.2827291,"lon":-123.12073750000002}],"unit":"km"}}]}]]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort]; }
at org.elasticsearch.action.search.AbstractSearchAsyncAction.onFirstPhaseResult(AbstractSearchAsyncAction.java:206)
at org.elasticsearch.action.search.AbstractSearchAsyncAction$1.onFailure(AbstractSearchAsyncAction.java:152)
at org.elasticsearch.action.ActionListenerResponseHandler.handleException(ActionListenerResponseHandler.java:46)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.processException(TransportService.java:855)
at org.elasticsearch.transport.TransportService$DirectResponseChannel.sendResponse(TransportService.java:833)
at org.elasticsearch.transport.TransportService$4.onFailure(TransportService.java:387)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: NotSerializableExceptionWrapper[: failed to find mapper for [user.location] for geo distance based sort]; nested: IllegalArgumentException[failed to find mapper for [user.location] for geo distance based sort];
at org.elasticsearch.ElasticsearchException.guessRootCauses(ElasticsearchException.java:386)
at org.elasticsearch.action.search.SearchPhaseExecutionException.guessRootCauses(SearchPhaseExecutionException.java:152)
at org.elasticsearch.action.search.SearchPhaseExecutionException.getCause(SearchPhaseExecutionException.java:99)
at org.elasticsearch.ElasticsearchException.writeTo(ElasticsearchException.java:226)
at org.elasticsearch.action.search.SearchPhaseExecutionException.writeTo(SearchPhaseExecutionException.java:64)
at org.elasticsearch.common.io.stream.StreamOutput.writeThrowable(StreamOutput.java:564)
at org.elasticsearch.ElasticsearchException.writeTo(ElasticsearchException.java:226)
at org.elasticsearch.transport.ActionTransportException.writeTo(ActionTransportException.java:64)
at org.elasticsearch.common.io.stream.StreamOutput.writeThrowable(StreamOutput.java:564)
at org.elasticsearch.transport.netty.NettyTransportChannel.sendResponse(NettyTransportChannel.java:120)
at org.elasticsearch.transport.DelegatingTransportChannel.sendResponse(DelegatingTransportChannel.java:68)
at org.elasticsearch.transport.RequestHandlerRegistry$TransportChannelWrapper.sendResponse(RequestHandlerRegistry.java:146)
at org.elasticsearch.action.support.HandledTransportAction$TransportHandler$1.onFailure(HandledTransportAction.java:74)
at org.elasticsearch.action.search.AbstractSearchAsyncAction.raiseEarlyFailure(AbstractSearchAsyncAction.java:294)
... 10 more
Caused by: java.lang.IllegalArgumentException: failed to find mapper for [user.location] for geo distance based sort
at org.elasticsearch.search.sort.GeoDistanceSortParser.parse(GeoDistanceSortParser.java:161)
at org.elasticsearch.search.sort.SortParseElement.addCompoundSortField(SortParseElement.java:141)
at org.elasticsearch.search.sort.SortParseElement.parse(SortParseElement.java:84)
at org.elasticsearch.search.SearchService.parseSource(SearchService.java:838)
at org.elasticsearch.search.SearchService.createContext(SearchService.java:654)
at org.elasticsearch.search.SearchService.createAndPutContext(SearchService.java:620)
at org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:371)
at org.elasticsearch.search.action.SearchServiceTransportAction$SearchQueryTransportHandler.messageReceived(SearchServiceTransportAction.java:368)
at org.elasticsearch.search.action.SearchServiceTransportAction$SearchQueryTransportHandler.messageReceived(SearchServiceTransportAction.java:365)
at org.elasticsearch.transport.TransportRequestHandler.messageReceived(TransportRequestHandler.java:33)
at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:75)
at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:376)
at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
... 3 more
这是触发异常的java方法:
@Override
public List<User> getCollaboratorsBasedOnLocation(Collection<User> ignoredUsers, double lat, double lon, int limit){
List<User> foundUsers = new ArrayList<User>();
try {
Client client = ElasticSearchFactory.getClient();
QueryBuilder qb = new MatchAllQueryBuilder();
BoolQueryBuilder bQueryBuilder = QueryBuilders.boolQuery();
bQueryBuilder.should(qb);
for (User ignUser : ignoredUsers) {
if (ignUser != null) {
bQueryBuilder.mustNot(termQuery("id", ignUser.getId()));
}
}
GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("user.location")
.point(lat, lon)
.unit(DistanceUnit.KILOMETERS)
.order(SortOrder.ASC);
SearchResponse sResponse = client
.prepareSearch(ESIndexNames.INDEX_USERS)
.setTypes(ESIndexTypes.USER)
.setQuery(bQueryBuilder)
.addSort(sortBuilder)
.setFrom(0)
.setSize(limit)
.execute()
.actionGet();
foundUsers = this.convertSearchResponseToUsersList(sResponse);
} catch (NoNodeAvailableException e1) {
logger.error(e1);
}
return foundUsers;
}
解决方案
事实证明问题出在算法的排序部分的路径中。这是不正确的,并在更改&#34; user.location&#34;到&#34;位置&#34;一切都恢复正常。