在我的ElasticSearch索引中,location是一个MultiValueField。当我为涉及位置的文档编写自定义评分公式时,我希望脚本选择最接近查询点的位置。
所以,我有我的评分公式的这一部分:
...
if (!doc['location'].empty && doc['location'].values.length > 1) {
least_distance = 10000;
foreach (loc_index: doc['location'].values) {
temp_distance = loc_index.distance(lat, lng);
if (temp_distance < least_distance) {
least_distance = temp_distance;
}
...
它不是最优雅的(我是mvel和ES的新手),但从概念上讲,我首先要检查doc["location"]中是否确实有多个位置,如果有,请遍历每个位置来计算距离,并跟踪到目前为止找到的最小距离。
当我这样做时,ElasticSearch返回一个错误:
Query Failed [Failed to execute main query]]; nested: PropertyAccessException[[Error: unable to resolve method: org.elasticsearch.common.geo.GeoPoint.distance(java.lang.Double, java.lang.Double)
我认为这意味着它不想在GeoPoint上执行.dancee(),由于某种原因,这与我通过执行doc["location"]可能获得的字段不同。
我对这种情况的解释正确吗?有人知道变通办法吗?有没有一种方法可以使用ElasticSearch计算距离(理想情况下不需要实际计算两个坐标之间的距离)?
这里的问题是调用.values
会给出GeoPoint()
对象的列表。尽管我们需要做一些额外的工作来引入适当的Java类,但还是有一些变通办法的。我们需要知道两个点的纬度和经度。
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
base_point = doc['base_location'].value;
if (!doc['location'].empty && doc['location'].values.length > 1) {
foreach (loc_index: doc['location'].values) {
distance = GeoDistance.PLANE.calculate(loc_index.lat, loc_index.lon, base_point.lat, base_point.lon, DistanceUnit.MILES);
}
}
我们可以用这里的可枚举数描述的不同单位得到结果。我们还可以使用不同的计算方法(如ARC),如下所述。