UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Elasticsearch】緯度経度を使って検索する

ホテルなどの宿泊施設をGoogle Map 上にマーカーを表示することを考えたとき、 Google Mapの中心を動かすと同時に(または何かボタンを押して)その四隅の緯度経度内にはいる施設を再検索をしたい

これを実現するためにElasticsearchのGeo-bounding box queryを使用してみる

Geo-bounding box queryはESのドキュメント(施設)の位置情報を基にフィルタリングするためのクエリ

www.elastic.co

施設のドキュメントにはlatitudelongitudeがペアに保持されるgeo_pointtypeのフィールドがある必要がある

Geo-point datatype | Elasticsearch Reference [7.x] | Elastic

PUT my_index
{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}

PUT my_index/_doc/1
{
  "text": "Geo-point as an object",
  "location": { 
    "lat": 41.12,
    "lon": -71.34
  }
}

保持のしかたは他にも以下のようなやり方が可能

PUT my_index/_doc/2
{
  "text": "Geo-point as a string",
  "location": "41.12,-71.34" 
}

PUT my_index/_doc/3
{
  "text": "Geo-point as a geohash",
  "location": "drm3btev3e86" 
}

PUT my_index/_doc/4
{
  "text": "Geo-point as an array",
  "location": [ -71.34, 41.12 ] 
}

PUT my_index/_doc/5
{
  "text": "Geo-point as a WKT POINT primitive",
  "location" : "POINT (-71.34 41.12)" 
}

このでフィールドに対して検索をかける

指定したエリアの範囲で検索する場合

エリアの左上右下の緯度経度を使って以下のようなクエリをつくる

GET my_index/_search
{
    "query": {
        "bool" : {
            "must" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_bounding_box" : {
                    "location" : {
                        "top_left": {
                            "lat": 42,
                            "lon": -72
                        },
                        "bottom_right": {
                            "lat": 40,
                            "lon": -74
                        }
                    }
                }
            }
        }
    }
}

指定した中心からの距離で検索かける場合

GET /my_locations/_search
{
    "query": {
        "bool" : {
            "must" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_distance" : {
                    "distance" : "200km",
                    "location" : {
                        "lat" : 40,
                        "lon" : -70
                    }
                }
            }
        }
    }
}

distanceのunitはこちら

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/common-options.html#distance-units

指定した多角形の図形内で検索かける場合

GET /my_locations/_search
{
    "query": {
        "bool" : {
            "must" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_polygon" : {
                    "location" : {
                        "points": [
                            [40, -70],
                            [30, -80],
                            [20, -90]
                        ]
                    }
                }
            }
        }
    }
}