ElasticSearch гео-дистанционный фильтр с несколькими местоположениями в массиве - возможно? - программирование
Подтвердить что ты не робот

ElasticSearch гео-дистанционный фильтр с несколькими местоположениями в массиве - возможно?

Скажем, у нас есть куча документов в индексе ElasticSearch. Каждый документ имеет несколько местоположений в массиве, например:

{
  "name": "foobar",
  "locations": [
    {
      "lat": 40.708519,
      "lon": -74.003212
    },
    {
      "lat": 39.752609,
      "lon": -104.998100
    },
    {
      "lat": 51.506321,
      "lon": -0.127140
    }
  ]
}

В соответствии с справочником ElasticSearch

фильтр geo_distance может работать с несколькими местоположениями/точками за документ. Когда одно место/точка совпадает с фильтром, документ будет включен в фильтр.

Итак, возможно ли создать фильтр геоданных, который проверяет все местоположения в массиве?

Это, похоже, не работает, к сожалению:

{
  "filter": {
    "geo_distance": {
      "distance": "100 km",
      "locations": "40, -105"
    }
  }
}

throws "QueryParsingException[[myIndex] failed to find geo_point field [locations]", поскольку locations не является одним geo_point, а массивом geo_point s.

4b9b3361

Ответ 1

Вы указали сопоставление geo_point для вашего документа?

curl -XDELETE 'http://localhost:9200/twitter/'
curl -XPUT 'http://localhost:9200/twitter/'

curl -XPUT 'http://localhost:9200/twitter/tweet/_mapping' -d '
{
    "tweet" : {
        "properties" : {
            "locations" : {"type" : "geo_point"}
        }
    }
}'

curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '
{ 
    "user": "kimchy", 
    "postDate": "2009-11-15T13:12:00", 
    "message": "Trying out Elastic Search, so far so good?",
    "locations" : [{
        "lat" : 50.00,
        "lon" : 10.00
    },
    {
        "lat" : 40.00,
        "lon" : 9.00
    }]
}'

curl -XPUT 'http://localhost:9200/twitter/tweet/2' -d '
{ 
    "user": "kimchy", 
    "postDate": "2009-11-15T13:12:00", 
    "message": "Trying out Elastic Search, so far so good?",
    "locations" : [{
        "lat" : 30.00,
        "lon" : 8.00
    },
    {
        "lat" : 20.00,
        "lon" : 7.00
    }]
}'

curl -XGET 'http://localhost:9200/twitter/tweet/_search' -d '{
    "query": {
        "filtered" : {
            "query" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_distance" : {
                    "distance" : "20km",
                    "tweet.locations" : {
                        "lat" : 40.00,
                        "lon" : 9.00
                    }
                }
            }
        }
    }
}'

Ответ 2

Для версии Elasticsearch версии 5.1 для того же выше индекса запрос будет выглядеть следующим образом:

curl -XGET 'http://localhost:9200/twitter/tweet/_search' -d '
{
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "200km",
                    "locations": {
                        "lat": 40.00,
                        "lon": 9.00
                    }
                }
            }
        }
    }
}'