ElasticSearch GeoLocation 官方文档翻译之 Geo Point

Geo Points

Geo-points 就是我们地球的经纬度,它能够用于计算地球两点之间的距离。

Geo-points 不能使用动态mapping,必须提前制定好geo_point类型

PUT /attractions
{
  "mappings": {
    "restaurant": {
      "properties": {
        "name": {
          "type": "string"
        },
        "location": {
          "type": "geo_point"
        }
      }
    }
  }
}

Lat/Lon Formats

假设我们把 location 字段定义为geo_point 类型,我们创建文档的时候应该包含一对 latitude/longitude ,可以是 string ,arrays 或者 objects

PUT /attractions/restaurant/1
{
  "name":     "Chipotle Mexican Grill",
  "location": "40.715, -74.011" 
}

PUT /attractions/restaurant/2
{
  "name":     "Pala Pizza",
  "location": { 
    "lat":     40.722,
    "lon":    -73.989
  }
}

PUT /attractions/restaurant/3
{
  "name":     "Mini Munchies Pizza",
  "location": [ -73.983, 40.719 ] 
}

注意:

latitude/longitude 在每种类型的顺序是不一样的,在字符串中是"latitude,longitude",但是在数组中应为[longitude,latitude],

以前,字符串和数组中的经纬度顺序是一致的,但是为了和GeoJSON保持一致,所以讲数组的经纬度顺序颠倒了。

Filtering by Geo Point

四种geo-point filters 可以帮助我们去过滤数据,当我们使用geolocation时。

geo_bounding_box:
找出落在一个指定的长方形中的geo-points
geo_distance:
找出以一个点为中心,一个指定半径范围内的geo-points
geo_distance_range:
找出以一个点为中心,设置一个最小半径和一个最大半径,在这个之间的geo-points
geo_polygon:
找出落在一个多边形范围内的geo-points,这个代价是相当昂贵的,如果你有这样的需求,建议使用 geo-shapes

每种filter的计算一个点是否落到一个区域的方式有些不同,但过程都是相似的。
所请求的区域被转换为quad/geohash前缀标记的范围,然后去倒排索引中搜索具有相同标记的文档。

建议:

Geo-filters 是相当耗费性能的,它适合用于在文档数量较少的时候。首先,你应该利用其它filter先过滤掉一部分数据。

Geo Bounding Box Filter

它是到目前为止最有效率的filter,因为他的计算非常简单。你只需提供上、下、左、右四个坐标,剩下的就是他会比较longitude 是否在左右坐标内,latitude 是否在上下坐标内

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_bounding_box": {
          "location": { 
            "top_left": {
              "lat":  40.8,
              "lon": -74.0
            },
            "bottom_right": {
              "lat":  40.7,
              "lon": -73.0
            }
          }
        }
      }
    }
  }
}

Optimizing Bounding Boxes

geo_bounding_box 是不需要将所有的geo-points都加载到内存的。因为它需要做的就是检查the lat and lon 是否落到了一个指定的区域。它可以用倒排索引去做个一次过滤。

为了使用这种优化,我们必须指定geo_point 的映射,设置 "lat_lon": true

PUT /attractions
{
  "mappings": {
    "restaurant": {
      "properties": {
        "name": {
          "type": "string"
        },
        "location": {
          "type":    "geo_point",
          "lat_lon": true 
        }
      }
    }
  }
}

现在,当你执行下面的查询时,我们会告诉elasticsearch使用lat 和lon的索引

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_bounding_box": {
          "type":    "indexed", 
          "location": {
            "top_left": {
              "lat":  40.8,
              "lon": -74.0
            },
            "bottom_right": {
              "lat":  40.7,
              "lon":  -73.0
            }
          }
        }
      }
    }
  }
}

Geo Distance Filter

geo_distance 这个过滤器会画个圆,来找到在这个落在这个圆内所有的文档

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance": {
          "distance": "1km", 
          "location": { 
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}

geo-distance 的搜索是相当耗费性能的,为了优化,elasticsearch会首先会画一个内切于圆的正方形。然后用bounding-box filter 过滤掉一部分数据。然后在执行geo-distance filter去找到那些落在圆内的数据。

Faster Geo-Distance Calculations

两点之间的距离可以利用一个牺牲性能来提高精度的算法去计算

arc:
最慢但是精度最高的就是arc 了,一个把地球看成一个球体,但是精度还是有限的,因为实际上地球并不是一个真正的球体
plane:
plane 算法把地球看成扁平的。它很快但是精度低。在赤道精度最高。
sloppy_arc:
这么称呼他是因为这个算法是粗滤的计算。

在查询的时候,你可以和下面一样,指定一个算法

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance": {
          "distance":      "1km",
          "distance_type": "plane", 
          "location": {
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}

geo_distance_range Filter

geo_distance 和 geo_distance_range 的唯一区别是,geo_distance_range是一个圆环。

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance_range": {
          "gte":    "1km", 
          "lt":     "2km", 
          "location": {
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}

Sorting by Distance

查询结果是可以跟到一个点的距离排序的

GET /attractions/restaurant/_search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_bounding_box": {
          "type":       "indexed",
          "location": {
            "top_left": {
              "lat":  40.8,
              "lon": -74.0
            },
            "bottom_right": {
              "lat":  40.4,
              "lon": -73.0
            }
          }
        }
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": { 
          "lat":  40.715,
          "lon": -73.998
        },
        "order":         "asc",
        "unit":          "km", 
        "distance_type": "plane" 
      }
    }
  ]
}

你可以问问你自己,为什么要指定距离单位,排序?这不取决于我们用米、千米而产生不同的结果。真是的原因是排序的时候会返回结果

...
  "hits": [
     {
        "_index": "attractions",
        "_type": "restaurant",
        "_id": "2",
        "_score": null,
        "_source": {
           "name": "New Malaysia",
           "location": {
              "lat": 40.715,
              "lon": -73.997
           }
        },
        "sort": [
           0.08425653647614346 
        ]
     },
...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容