一、背景

最近有个需要,须要获取某个地位左近的楼盘,比方:获取以后用户所在位置,方圆100km千米之内的楼盘信息。通过调研,发现能够应用 redismongodbelasticsearch等实现。通过思考之后决定应用es来实现,此处简略记录下esgeo方面api的应用。

二、geo数据类型

es中存在2种地理位置数据类型,geo_pointgeo_shapees无奈自动识别这种数据类型,须要在创立mapping的时候,本人手动指定。

1、geo_point

geo_point应用的是经纬度的坐标点,能够计算落在某个矩形内的点、以某个点为半径(圆)的点、某个多边形内的点(弃用了)、排序、聚合等操作。

2、geo_shape

geo_shape示意的是一个简单的图形,应用的是GeoJSON的格局来示意简单的图形。比方:咱们要示意一个图书馆的坐标地位,如果图书馆占的地位比拟大,用一个点示意可能就不准了,此时就能够应用geo_shape来示意了。

不过这种数据类型也有毛病:比方不能排序等等(因为是多边形的点)。

三、此处对geo_point类型实战

1、背景

1、图中的 ① ② ③ ④ 示意是须要退出到 es 中的建筑物

建筑物坐标间隔地点相隔间隔解释
上海站121.462311,31.256224上海站
上海静安洲际酒店121.460186,31.251281上海站586.24米上海站和该酒店大略像个586.24米
交通公园121.473939,31.253531上海站1146.45米
万业近景大厦121.448215,31.26229上海站1501.74米

2、图中的圆形、正方形、多边形示意前期须要应用 es 查问进去外面外面的地点。

3、图中的短小的箭头➡️示意边界。

2、插入地点数据

1、创立索引

PUT /geo_index{  "settings": {    "number_of_shards": 2,    "number_of_replicas": 2,    "analysis": {      "analyzer": {        "default": {          "type": "ik_max_word"        }      }    }  },  "mappings": {    "properties": {      "building_name": {        "type": "keyword"      },      "location": {        // 此处手动指定数据类型        "type": "geo_point"      }    }  }}

留神⚠️:

1、在索引中,咱们本人指定来location字段的类型为geo_point类型。

2、building_name的字段类型为keyword示意不分词,这个字段只是为了测试,没有什么用。

3、不必指定索引的type,在es7中只有一个type。

2、插入地理位置数据

POST _bulk{"create":{"_index":"geo_index","_id":1}}{"building_name":"上海站","location":{"lat":31.256224,"lon":121.462311}}{"create":{"_index":"geo_index","_id":2}}{"building_name":"上海静安洲际酒店","location":"POINT (121.460186 31.251281)"}{"create":{"_index":"geo_index","_id":3}}{"building_name":"交通公园","location":"31.253531,121.473939"}{"create":{"_index":"geo_index","_id":4}}{"building_name":"万业近景大厦","location":[121.448215,31.26229]}

留神⚠️:

1、从下面可知:地理位置的插入的格局能够存在4种形式。

1、 {"lat":"","lon":""}2、 "lat,lon"3、 [Well-Known Text](https://docs.opengeospatial.org/is/12-063r5/12-063r5.html) "POINT (lon lat)"4、 [lon,lat]5、 还有一种 geohash 的格局须要留神的是:应用 数组/Well-Known-Text 的格局的时候,经纬度是反过来的。

3、执行检索

1、geo_bounding_box 矩形过滤

从上图可知左上角和右下方的坐标别离为 (121.444075,31.265395)和(121.468417,31.253845)

执行查问,应该能够查问出 上海站万业近景大厦

1、es查问语句

GET /geo_index/_search{  "query": {    "bool": {      "must": {        "match_all": {}      },      "filter": {        "geo_bounding_box": {          "location": {            "top_left": {              "lat": 31.265395,              "lon": 121.444075            },            "bottom_right": {              "lat": 31.253845,              "lon": 121.468417            }          }        }      }    }  }}

2、查问后果

从图中能够看到,查问进去了 上海站万业近景大厦,后果是正确的。

2、geo_distance 圆形查问

这个是间隔查问,是以某个点向四周扩算的间隔范畴。

在上一步的背景中,咱们晓得上海站的坐标(121.462311,31.256224),同时也晓得了上海站间隔各个周边的间隔有多远,此处咱们以上海站为核心,查问方圆600米的建筑物,可知只有上海静安洲际酒店上海站合乎。

1、es查问语句

GET /geo_index/_search{  "query": {    "bool": {      "must": {        "match_all": {}      },      "filter": {        "geo_distance": {          "distance": "600m",          "distance_type": "arc",           "_name":"optional_name",          "location": {            "lat": 31.256224,            "lon": 121.462311          }        }      }    }  }}

留神⚠️:

1、distance_type的值存在2个 arcplane

  • arc:默认的形式,这种形式计算比拟准确,然而比较慢,是把地球当作一个球体计算。
  • plane:这种形式计算比拟快,然而可能不怎么准,越凑近赤道越准,是把地球当成平坦的进行计算。

2、distance前面可用的单位有kmmcmmmnmimiydftin

2、查问后果

3、geo_distance 查问并排序,返回间隔相隔多少米

1、es 查问语句

GET /geo_index/_search{  "query": {    "bool": {      "must": {        "match_all": {}      },      "filter": {        "geo_distance": {          "distance": "600m",          "distance_type": "arc",          "_name": "optional_name",          "location": {            "lat": 31.256224,            "lon": 121.462311          }        }      }    }  },  "sort": [    {      "_geo_distance": {        "location": {          "lat": 31.256224,          "lon": 121.462311        },        "order": "desc",        "unit": "m",        "distance_type": "arc"      }    }  ]}

留神⚠️:

1、sort执行排序。

2、查问后果

4、geo_distance聚合

需要:

1. 统计`上海站`500米之内的建筑物有多少。 2. 统计`上海站`500-1000米之内的建筑物有多少。 3. 统计`上海站`大于1000米的建筑物有多少。

1、es查问语句

GET /geo_index/_search{  "query": {    "bool": {      "must": {        "match_all": {}      }    }  },  "aggs": {    "rings_around_amsterdam": {      "geo_distance": {        "field": "location",        "origin": {          "lat": 31.256224,          "lon": 121.462311        },        "unit": "m",        "distance_type": "arc",        "ranges": [          {"to": 500,"key": "first"},          {"from": 500,"to": 1000,"key": "second" },          {"from": 1000,"key": "third"}        ],        "keyed": true      }    }  }}

2、查问后果

从上图中能够看到:

1、间隔上海站在 0-500米之间的建筑物只有1个。

2、间隔上海站在 500-1000之间的建筑物有1个。

3、间隔上海站在 1000以上的有2个。

5、geo-polygon-多边形查问(过期)

在 es7.12 中曾经过期了,举荐应用 geo_shape来实现

6、一个综合案例

1、需要:

1、查问语句query,查问出所有的数据,并过滤出以上海站为核心的3km内的所有的建筑物。

2、aggs,用于统计出上海在 500米以内、500-1000米、1000米之外的建筑物数量。

3、sort用于排序。

4、post_filter用于将后果放大到上海站1000米以内。

2、查问后果

GET /geo_index/_search{  "query": {    "bool": {      "must": {        "match_all": {}      }, // 过滤出上海站四周3km范畴内的建筑物      "filter": {        "geo_distance": {          "distance": "3km",          "distance_type": "arc",           "_name":"optional_name",          "location": {            "lat": 31.256224,            "lon": 121.462311          }        }      }    }  }, // 聚合上海站四周的建筑物的数量  "aggs": {    "rings_around_amsterdam": {      "geo_distance": {        "field": "location",        "origin": {          "lat": 31.256224,          "lon": 121.462311        },        "unit": "m",        "distance_type": "arc",        "ranges": [          {"to": 500,"key": "first"},          {"from": 500,"to": 1000,"key": "second" },          {"from": 1000,"key": "third"}        ],        "keyed": true      }    }  },// 对查问到的后果排序,并将间隔放到响应数据的 sort 字段中。  "sort": [    {      "_geo_distance": {        "location": {          "lat": 31.256224,          "lon": 121.462311        },        "order": "desc",        "unit": "m",        "distance_type": "arc"      }    }  ],// 将后果放大到上海站左近1km的范畴内。  "post_filter": {    "geo_distance": {      "distance": "1km",      "location": {        "lat": 31.256224,        "lon": 121.462311      }    }  }}

四、参考文档

1、geo_point数据类型

2、间隔单位

3、排序

4、矩形查问

5、圆形查问,间隔查问

6、坐标拾取零碎