大数据利器Elasticsearch搜索之地理坐标GEO

875 阅读2分钟

这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
本Elasticsearch相关文章的版本为:7.4.2

在Elasticsearch应用中,较为常见的就是地图应用。地理坐标GEO就是使用经纬度表示地球上的一个点。利用地理坐标可以计算两个坐标点之间的距离或计算某个点是否落在特定的区域内,使用Elasticsearch可以非常便捷的得到结果。

geo类型声明

地理坐标点需要在mapping里面显式声明,不能动态自动映射。

PUT /geo_test_index
{
  "mappings": {
      "properties": {
        "hotel_name": {
          "type": "text"
        },
        "location": {
          "type": "geo_point"
        }
      }
  }
}

geo坐标数据格式

Elasticsearch支持字符串、对象、数组三种方式进行提交geo数据:

  • 字符串形式:以英文半角逗号隔开,纬度在前经度在后
  • 对象形式:以lat显式纬度的值,lon显式经度的值
  • 数组形式:经度在前纬度在后
    下面是上述三种geo坐标数据格式的例子:
PUT /geo_test_index/_doc/1
{
  "city":     "city a",
  "location": "32.231, 45.78" 
}

PUT /geo_test_index/_doc/2
{
  "city":     "city b",
  "location": { 
    "lat":     32.232,
    "lon":    45.78
  }
}

PUT /geo_test_index/_doc/3
{
  "city":     "city c",
  "location": [ 45.78, 32.233 ] 
}

特定距离范围内数据查询

Elasticsearch里面可以以某一点作为中心点,查询半径范围为的数据。下面的例子是以纬度23.232经度45.78为中心点,获取半径20km范围内的数据:

GET /geo_test_index/_search
{
  "query": {
    "bool": {
      "filter": {
        "geo_distance": {
          "distance": "20km", 
          "location": { 
            "lat":  32.232,
            "lon": 45.78
          }
        }
      }
    }
  }
}

获取矩形边框内数据查询

Elasticsearch除了支持查询某个半径内的数据外,还支持查询给出左上角和右下角构建出的矩形地理范围内的数据。下面的例子就是在查询由左上角纬度32.3经度45.7和右下角纬度32.1经度45.8构建出的矩形地理范围内的数据:

GET /geo_test_index/_search
{
  "query": {
    "bool": {
      "filter": {
        "geo_bounding_box": {
          "location": { 
            "top_left": {
              "lat":  32.3,
              "lon": 45.7
            },
            "bottom_right": {
              "lat":  32.1,
              "lon": 45.8 
            }
          }
        }
      }
    }
  }
}

搜索结果按距离排序

一般地图应用里面,都会按照距离用户所在的位置远近进行排序后返回。下面的查询是返回特定范围内的数据并且根据距离某个地理位置有近到远返回数据:

GET /geo_test_index/_search
{
  "query": {
    "bool": {
      "filter": {
        "geo_bounding_box": {
          "type":       "indexed",
          "location": { 
            "top_left": {
              "lat":  32.3,
              "lon": 45.7
            },
            "bottom_right": {
              "lat":  32.1,
              "lon": 45.8 
            }
          }
        }
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": { 
          "lat":  32.2,
          "lon": 45.76
        },
        "order":         "asc",
        "unit":          "km", 
        "distance_type": "plane" 
      }
    }
  ]
}