2015-09-16 2 views
0

Я использую Elasticsearch для хранения местоположений пользователей и их предпочтения на расстоянии при поиске других пользователей. Он хранится в location geo_point и distance целых числах.Найти подходящие местоположения/расстояния без использования скриптов в Elasticsearch?

Например, индекс содержит следующие документы:

  • Alice, расположенный в [0,100] и ищет пользователей в пределах 100 метров;
  • Bob, расположенный по адресу [100,0] и ищет пользователей в пределах 50 метров.

Когда Карлос, расположенный в [0,0], поиски в пределах 100 метров мне нужен мой запрос, чтобы вернуть Алису, но не Боб (так как Боб хочет только пользователи в пределах 50 м, и Карлос находится в 100 км).

Другими словами, я хочу, чтобы вернуть все документы D таким образом, что D.reach содержит Carlos.location и Carlos.reach содержит D.location.

Насколько я могу видеть, единственный способ сделать это путем сравнения расстояний с помощью сценариев, как так:

{ 
    "filter": { 
     "script": { 
      "script": "min(doc['distance'].value, distance) >= doc['location'].arcDistance(lat, lon)", 
      "params": { 
       "distance": 100, 
       "lat": 0, 
       "lon": 0 
      } 
     } 
    } 
} 

Однако, я бы rather avoid scripting, если это вообще возможно. Есть ли альтернативный метод для достижения этого?

ответ

0

Благодаря ответу Val, указывающему на меня в правильном направлении, я использовал следующее решение.

Документы выглядят так: geo_point и достигают geo_shape.

{ 
    "name": "Alice", 
    "location" : [1,0], 
    "reach" : { 
     "type": "shape", 
     "coordinates": [1,0], 
     "radius": 100 
    } 
} 

Запрос содержит два фильтра; один для соответствия местоположения Карлоса в пределах досягаемости пользователей, а другой для соответствия местоположению пользователя внутри досягаемости Карлоса.

{ 
    "filter": { 
     "and" : [ 
      { 
       "geo_shape": { 
        "preferences.reach": { 
         "shape": { 
          "type": "Point", 
          "coordinates": Carlos.location 
         } 
        } 
       } 
      }, 
      { 
       "geo_distance": { 
        "distance": Carlos.distance, 
        "user.location" : Carlos.location 
       } 
      } 
     ] 
    } 
} 

Это может быть сделано с двумя geo_shape с, но geo_point с более производительным.

0

Другой способ, которым стоит исследовать, будет использовать geo_shapecircle. Поэтому вместо (или в дополнение к) хранения дискретных значений для location и distance вы можете сохранить комбинацию этих двух значений в виде круга, представляющего пользователя reach. В вашем картографирования, это будет выглядеть следующим образом:

{ 
    "properties": { 
     "reach": { 
      "type": "geo_shape", 
      "tree": "quadtree", 
      "precision": "10cm" 
     } 
    } 
} 

Тогда, когда вы индексировать документ, вы бы указать reach круг вроде этого:

{ 
    "name": "Alice", 
    "reach" : { 
     "type" : "circle", 
     "coordinates" : [0.0, 100.0], <---- Alice's current location field 
     "radius" : "100m"    <---- Alice's current distance field 
    } 
} 
{ 
    "name": "Bob", 
    "reach" : { 
     "type" : "circle", 
     "coordinates" : [100.0, 0.0], <---- Bob's current location field 
     "radius" : "50m"     <---- Bob's current distance field 
    } 
} 

На данный момент, все пользователи будут иметь a geo_shape, связанный с ними, представляющий собой их охват. Теперь вы можете развернуть мощность гео-запросов и фильтров ES, чтобы найти перекрестки или что у вас есть, например, с помощью geo_shape filter. Идея заключается в том, чтобы фильтровать на другой geo_shape, представляющей досягаемость пользователя, который находится в поиске других пользователей (например, Карлос выше)

{ 
    "query":{ 
     "filtered": { 
      "filter": { 
       "geo_shape": { 
        "location": { 
         "shape": { 
          "type": "circle", 
          "coordinates" : [0.0, 0.0] <--- Carlos location 
          "radius": "100m"    <--- Carlos reach 
         } 
        } 
       } 
      } 
     } 
    } 
} 

выше запрос будет найти все документы (т.е. пользователей), чью длинна пересекает Карлос достигает указанное в фильтре. Дать ему шанс.

+0

Привет, спасибо за ответ, но это не совсем то, что мне нужно. Это вычислит пересечение A.reach и C.reach, тогда как я хочу обеспечить существование A.location внутри C.reach AND C.location существует внутри A.reach. Я уточню вопрос, чтобы уточнить. – Graham

+0

Предположительно, я мог бы использовать И для выполнения двух фильтров; один из которых обеспечивает форму «Точка» в соответствии с досягаемостью документа, а другой - форму круга в соответствии с местоположением документа? – Graham

+0

Да, вы тоже можете это сделать, если это было вашим намерением. Проверить, находится ли точка внутри круга, легко с помощью фильтра geo_shape. – Val

Смежные вопросы