• 地理距离过滤器
    • 更快的地理距离计算
    • 地理距离区间过滤器

    地理距离过滤器

    地理距离过滤器geo_distance)以给定位置为圆心画一个圆,来找出那些位置落在其中的文档:

    1. GET /attractions/restaurant/_search
    2. {
    3. "query": {
    4. "filtered": {
    5. "filter": {
    6. "geo_distance": {
    7. "distance": "1km", <1>
    8. "location": { <2>
    9. "lat": 40.715,
    10. "lon": -73.988
    11. }
    12. }
    13. }
    14. }
    15. }
    16. }
    • <1> 找出所有与指定点距离在1公里(1km)内的 location 字段。访问 Distance Units 查看所支持的距离表示单位

    • <2> 中心点可以表示为字符串,数组或者(如示例中的)对象。详见 lat-lon-formats。

    地理距离过滤器计算代价昂贵。
    为了优化性能,Elasticsearch 先画一个矩形框(边长为2倍距离)来围住整个圆形,
    这样就可以用消耗较少的盒模型计算方式来排除掉那些不在盒子内(自然也不在圆形内)的文档,
    然后只对落在盒模型内的这部分点用地理坐标计算方式处理。

    提示

    你需要判断你的使用场景,是否需要如此精确的使用圆模型来做距离过滤?
    通常使用矩形模型是更高效的方式,并且往往也能满足应用需求。

    更快的地理距离计算

    两点间的距离计算,有多种性能换精度的算法:

    • arc::

      最慢但是最精确是弧形arc)计算方式,这种方式把世界当作是球体来处理。
      不过这种方式精度还是有限,因为这个世界并不是完全的球体。

    • plane::

      平面plane)计算方式,(((“plane distance calculation”)))把地球当成是平坦的。
      这种方式快一些但是精度略逊;在赤道附近位置精度最好,而靠近两极则变差。

    • sloppy_arc::

      如此命名,是因为它使用了 Lucene 的 SloppyMath 类。
      这是一种用精度换取速度的计算方式,它使用 Haversine formula 来计算距离;
      它比弧形arc)计算方式快4~5倍, 并且距离精度达99.9%。这也是默认的计算方式。

    你可以参考下例来指定不同的计算方式:

    1. GET /attractions/restaurant/_search
    2. {
    3. "query": {
    4. "filtered": {
    5. "filter": {
    6. "geo_distance": {
    7. "distance": "1km",
    8. "distance_type": "plane", <1>
    9. "location": {
    10. "lat": 40.715,
    11. "lon": -73.988
    12. }
    13. }
    14. }
    15. }
    16. }
    17. }
    • <1> 使用更快但精度稍差的平面plane)计算方式。

    提示:
    你的用户真的会在意一个宾馆落在指定圆形区域数米之外了吗?
    一些地理位置相关的应用会有较高的精度要求;但大部分实际应用场景中,使用精度较低但响应更快的计算方式可能就挺好。

    地理距离区间过滤器

    地理距离过滤器geo_distance)和地理距离区间过滤器geo_distance_range)的唯一差别在于后者是一个环状的,它会排除掉落在内圈中的那部分文档。

    指定到中心点的距离也可以换一种表示方式:
    指定一个最小距离(使用 gt或者gte)和最大距离(使用lt或者lte),就像使用区间range)过滤器一样。

    1. GET /attractions/restaurant/_search
    2. {
    3. "query": {
    4. "filtered": {
    5. "filter": {
    6. "geo_distance_range": {
    7. "gte": "1km", <1>
    8. "lt": "2km", <1>
    9. "location": {
    10. "lat": 40.715,
    11. "lon": -73.988
    12. }
    13. }
    14. }
    15. }
    16. }
    17. }
    • <1> 匹配那些距离中心点超过1公里而小于2公里的位置。