ElasticSearch对地理数据查询(二)
在ElasticSearch中,地理位置通過geo_point這個(gè)數(shù)據(jù)類型來支持。地理位置的數(shù)據(jù)需要提供經(jīng)緯度信息,當(dāng)經(jīng)緯度不合法時(shí),ES會(huì)拒絕新增文檔。這種類型的數(shù)據(jù)支持距離計(jì)算,范圍查詢等。在底層,索引使用Geohash實(shí)現(xiàn)。
1、創(chuàng)建索引
PUT創(chuàng)建一個(gè)索引cn_large_cities,mapping為city:
{"mappings": {"city": {"properties": {"city": {"type": "string"},"state": {"type": "string"},"location": {"type": "geo_point"}}}} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
geo_point類型必須顯示指定,ES無法從數(shù)據(jù)中推斷。在ES中,位置數(shù)據(jù)可以通過對(duì)象,字符串,數(shù)組三種形式表示,分別如下:
# "lat,lon" "location":"40.715,-74.011""location": {"lat":40.715,"lon":-74.011 }# [lon ,lat] "location":[-74.011,40.715]- 1
POST下面4條測試數(shù)據(jù):
{"city": "Beijing", "state": "BJ","location": {"lat": "39.91667", "lon": "116.41667"}}{"city": "Shanghai", "state": "SH","location": {"lat": "34.50000", "lon": "121.43333"}}{"city": "Xiamen", "state": "FJ","location": {"lat": "24.46667", "lon": "118.10000"}}{"city": "Fuzhou", "state": "FJ","location": {"lat": "26.08333", "lon": "119.30000"}}{"city": "Guangzhou", "state": "GD","location": {"lat": "23.16667", "lon": "113.23333"}}- 1
查看全部文檔:
curl -X GET "http://localhost:9200/cn_large_cities/city/_search?pretty=true"- 1
- 1
返回全部的5條數(shù)據(jù),score均為1:
2、位置過濾
ES中有4中位置相關(guān)的過濾器,用于過濾位置信息:
- geo_distance: 查找距離某個(gè)中心點(diǎn)距離在一定范圍內(nèi)的位置
- geo_bounding_box: 查找某個(gè)長方形區(qū)域內(nèi)的位置
- geo_distance_range: 查找距離某個(gè)中心的距離在min和max之間的位置
- geo_polygon: 查找位于多邊形內(nèi)的地點(diǎn)。
geo_distance
該類型過濾器查找的范圍如下圖:
下面是一個(gè)查詢例子:
{"query":{"filtered":{"filter":{"geo_distance":"1km","location":{"lat":40.715,"lon": -73.988 }}}} }- 1
以下查詢,查找距廈門500公里以內(nèi)的城市:
{"query":{"filtered":{"filter":{"geo_distance" : {"distance" : "500km","location" : { "lat" : 24.46667, "lon" : 118.10000 } }}}} }- 16
geo_distance_range
{"query":{"filtered":{"filter":{"geo_distance_range":{"gte": "1km","lt": "2km","location":{ "lat":40.715, "lon": -73.988 } }}} }- 1
- 6
geo_bounding_box
{"query":{"filtered":{"filter":{"geo_bounding_box":{"location":{ "top_left":{ "lat": 40.8, "lon":-74.0 }, "bottom_right":{ "lat":40.715, "lon": -73.0 } } }}} }- 20
3、按距離排序
接著我們按照距離廈門遠(yuǎn)近查找:
{"sort" : [{"_geo_distance" : {"location" : {"lat" : 24.46667,"lon" : 118.10000}, "order" : "asc","unit" : "km"}}],"query": {"filtered" : {"query" : {"match_all" : {}}}} }結(jié)果如下,依次是廈門、福州、廣州…。符合我們的常識(shí):
{"took": 8,"timed_out": false,"_shards": {"total": 5,"successful": 5,"failed": 0},"hits": {"total": 5,"max_score": null,"hits": [{"_index": "us_large_cities","_type": "city","_id": "AVaiSGXXjL0tfmRppc_p","_score": null,"_source": {"city": "Xiamen","state": "FJ","location": {"lat": "24.46667","lon": "118.10000" }},"sort": [0]},{"_index": "us_large_cities","_type": "city","_id": "AVaiSSuNjL0tfmRppc_r","_score": null,"_source": {"city": "Fuzhou","state": "FJ","location": {"lat": "26.08333","lon": "119.30000" }},"sort": [216.61105485607183]},{"_index": "us_large_cities","_type": "city","_id": "AVaiSd02jL0tfmRppc_s","_score": null,"_source": {"city": "Guangzhou","state": "GD","location": {"lat": "23.16667","lon": "113.23333" }},"sort": [515.9964950041397]},{"_index": "us_large_cities","_type": "city","_id": "AVaiR7_5jL0tfmRppc_o","_score": null,"_source": {"city": "Shanghai","state": "SH","location": {"lat": "34.50000","lon": "121.43333" }},"sort": [1161.512141925948]},{"_index": "us_large_cities","_type": "city","_id": "AVaiRwLUjL0tfmRppc_n","_score": null,"_source": {"city": "Beijing","state": "BJ","location": {"lat": "39.91667","lon": "116.41667" }},"sort": [1725.4543712286697]}]} }- 1
結(jié)果返回的sort字段是指公里數(shù)。加上限制條件,只返回最近的一個(gè)城市:
{"from":0,"size":1,"sort" : [{"_geo_distance" : {"location" : {"lat" : 24.46667,"lon" : 118.10000}, "order" : "asc","unit" : "km"}}],"query": {"filtered" : {"query" : {"match_all" : {}}}} }4、地理位置聚合
ES提供了3種位置聚合:
- geo_distance: 根據(jù)到特定中心點(diǎn)的距離聚合
- geohash_grid: 根據(jù)Geohash的單元格(cell)聚合
- geo_bounds: 根據(jù)區(qū)域聚合
4.1 geo_distance聚合
下面這個(gè)查詢根據(jù)距離廈門的距離來聚合,返回0-500,500-8000km的聚合:
{"query":{"filtered":{"filter":{"geo_distance" : {"distance" : "10000km","location" : { "lat" : 24.46667, "lon" : 118.10000 } }}}},"aggs":{"per_ring":{"geo_distance":{"field": "location","unit": "km","origin":{"lat" : 24.46667,"lon" : 118.10000 },"ranges":[{"from": 0 , "to":500},{"from": 500 , "to":8000}]}}}}- 1
返回的聚合結(jié)果如下;
"aggregations": {"per_ring": {"buckets": [{"key": "*-500.0","from": 0,"from_as_string": "0.0","to": 500,"to_as_string": "500.0","doc_count": 2},{"key": "500.0-8000.0","from": 500,"from_as_string": "500.0","to": 8000,"to_as_string": "8000.0","doc_count": 3}]}}- 12
可以看到,距離廈門0-500km的城市有2個(gè),500-8000km的有3個(gè)。
4.2 geohash_grid聚合
該聚合方式根據(jù)geo_point數(shù)據(jù)對(duì)應(yīng)的geohash值所在的cell進(jìn)行聚合,cell的劃分精度通過precision屬性來控制,精度是指cell劃分的次數(shù)。
{"query":{"filtered":{"filter":{"geo_distance" : {"distance" : "10000km","location" : { "lat" : 24.46667, "lon" : 118.10000 } }}}},"aggs":{"grid_agg":{"geohash_grid":{"field": "location","precision": 2}}}}- 1
聚合結(jié)果如下:
"aggregations": {"grid_agg": {"buckets": [{"key": "ws","doc_count": 3},{"key": "wx","doc_count": 1},{"key": "ww","doc_count": 1}]}}- 1
可以看到,有3個(gè)城市的的geohash值為ws。將精度提高到5,聚合結(jié)果如下:
"aggregations": {"grid_agg": {"buckets": [{"key": "wx4g1","doc_count": 1},{"key": "wwnk7","doc_count": 1},{"key": "wssu6","doc_count": 1},{"key": "ws7gp","doc_count": 1},{"key": "ws0eb","doc_count": 1}]}}- 1
- 16
4.3 geo_bounds聚合
這個(gè)聚合操作計(jì)算能夠覆蓋所有查詢結(jié)果中g(shù)eo_point的最小區(qū)域,返回的是覆蓋所有位置的最小矩形:
{"query":{"filtered":{"filter":{"geo_distance" : {"distance" : "10000km","location" : { "lat" : 24.46667, "lon" : 118.10000 } }}}},"aggs":{"map-zoom":{"geo_bounds":{"field": "location"}}}}- 1
- 15
結(jié)果如下:
"aggregations": {"map-zoom": {"bounds": {"top_left": {"lat": 39.91666993126273,"lon": 113.2333298586309},"bottom_right": {"lat": 23.16666992381215,"lon": 121.43332997336984}}}}- 1
- 6
也就是說,這兩個(gè)點(diǎn)構(gòu)成的矩形能夠包含所有到廈門距離10000km的區(qū)域。我們把距離調(diào)整為500km,此時(shí)覆蓋這些城市的矩形如下:
"aggregations": {"map-zoom": {"bounds": {"top_left": {"lat": 26.083329990506172,"lon": 118.0999999679625},"bottom_right": {"lat": 24.46666999720037,"lon": 119.29999999701977}}}}- 1
- 2
5、參考資料
圖解 MongoDB 地理位置索引的實(shí)現(xiàn)原理:http://blog.nosqlfan.com/html/1811.html
Geopoint數(shù)據(jù)類型:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html
總結(jié)
以上是生活随笔為你收集整理的ElasticSearch对地理数据查询(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch对地理数据查询
- 下一篇: Bootstrap list-gro