Elasticsearch地理位置数据类型 - mouse3150/mouse3150.github.io GitHub Wiki

一、概述

空间地理类型,主要有两种类型,一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点、线、圈、多边形查询等。ElasticSearch支持基于地理位置的搜索和聚合分析,地理坐标点(geo-point) 是指地球表面可以用经纬度描述的一个点。地理坐标点可以用来计算两个坐标位置间的距离,或者判断一个点是否在一个区域中。地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo_point。

1.坐标点的表示形式:

  • 以半角逗号分割的字符串形式 “lat,lon”;
{
  "name":     "Chipotle Mexican Grill",
  "location": "40.715, -74.011"
}
  • 明确以lat和lon作为属性的对象;
{
  "name":     "Pala Pizza",
  "location": {
    "lat":     40.722,
    "lon":    -73.989
  }
}
  • 数组形式表示 [lon, lat]
{
  "name":     "Mini Munchies Pizza",
  "location": [ -73.983, 40.719 ]
}
注意 : 
可能所有人都至少踩过一次这个坑:地理坐标点用字符串形式表示时是纬度在前,经度在后(”latitude,longitude”),
而数组形式表示时刚好相反,是经度在前,纬度在后([longitude, latitude])。其实,在 Elasticesearch 内部,
不管字符串形式还是数组形式,都是纬度在前,经度在后。不过早期为了适配 GeoJSON 的格式规范,调整了数组形式的表示方式。
因此,在使用地理置(geolocation)的路上就出现了这么一个“捕熊器”。专坑那些不了解这个陷阱的使用者。

2.支持的空间运算函数

  • geo_bounding_box:: 找出落在指定矩形框中的坐标点
  • geo_distance:: 找出与指定位置在给定距离内的点
  • geo_distance_range:: 找出与指定点距离在给定最小距离和最大距离之间的点
  • geo_polygon:: 找出落在多边形中的点。这个过滤器使用代价很大。当你觉得自己需要使用它,最好先看看 geo-shapes(Why?)

三、过滤原理、问题及优化

原理: 基于空间运算函数过滤器的工作方式都相似: 把索引中所有文档(而不仅仅是查询中匹配到的部分文档[fielddata-itro])的经纬度信息都载入内存,然后每个过滤器执行一个轻量级的计算去判断当前点是否落在指定区域。

问题:过滤器的工作方式,地理坐标过滤器使用代价昂贵,所以最好在文档集合尽可能少的场景使用。 可以先使用那些简单、快捷的过滤器,比如 term或range,像时间(数据采集时间或入库时间)来过滤掉尽可能多的文档,最后才交给地理坐标过滤器处理。

布尔型过滤器(bool filter)会自动帮你做这件事。 它会优先让那些基于“bitset”的简单过滤器(见 filter-caching)来过滤掉尽可能多的文档,然后依次才是地理坐标过滤器或者脚本类的过滤器。

ES模型过滤器

  1. 地理坐标盒模型过滤器 这是最有效的地理坐标过滤器,因为它计算起来非常简单。 你指定一个矩形的 顶部(top), 底部(bottom), 左边界(left),和右边界(right),然后它只需判断坐标的经度是否在左右边界之间,纬度是否在上下边界之间。
GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_bounding_box": {
          "location": { <1>
            "top_left": {
              "lat":  40.8,
              "lon": -74.0
            },
            "bottom_right": {
              "lat":  40.7,
              "lon": -73.0
            }
          }
        }
      }
    }
  }
}

注: 盒模型信息也可以用 bottom_left(左下方点)和 top_right(右上方点) 来表示。

⚠️ **GitHub.com Fallback** ⚠️