Вычисление расстояния в местоположении MultiValueField

В моем индексе ElasticSearch местоположение — это 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)

что, я думаю, означает, что он не хочет выполнять .distance() для GeoPoint, что по какой-то причине отличается от поля, которое я мог бы получить, выполнив doc['location'].

Правильно ли я интерпретирую эту ситуацию, и кто-нибудь знает обходной путь? Есть ли способ просто рассчитать расстояние (в идеале, не вводя всю арифметику для расстояния между двумя координатами) с помощью ElasticSearch?


person ajyang818    schedule 06.01.2014    source источник


Ответы (1)


Проблема здесь в том, что вызов .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), описанные здесь.

person agross    schedule 23.01.2014