ElasticSearch GEO:地理坐标点(geo point)
跳到导航
跳到搜索
关于
在 ES 中地理坐标指的就是经度和纬度,ES 中存储经纬度坐标的数据类型为:geo_point。
定义geo_point类型映射
可以通过定义索引映射的时候,指定字段类型为 geo_point,表示存储的是一个经纬度坐标值。
示例:
PUT /shop
{
"mappings": {
"properties": {
"location": {
"type": "geo_point" // location字段的类型为geo_point
}
}
}
}
geo_point的存储格式
保存 geo_point 类型的数据主要有下面几种格式:
PUT /shop/_doc/1 { "location": { "lat": 41.12, "lon": -71.34 } }
- lat:纬度
- lon:经度
PUT /shop/_doc/2 { "location": [ -71.34, 41.12 ] }
- [ 经度, 纬度]:以数组的形式存储经纬度
PUT /shop/_doc/3 { "location": "41.12,-71.34" }
- "纬度,经度":以字符串的形式存储经纬度
按距离搜索(geo_distance)
如果 ES 索引的字段类型为:geo_point,我们就可以按距离搜索文档。
示例:
- 创建店铺索引:
PUT /shops { "mappings": { "properties": { "id": { // 店铺Id "type": "integer" }, "title": { // 店铺名 "type": "text" }, "location": { // 店铺经纬度 "type": "geo_point" } } } }
- 按距离搜索:通过 geo_distance 搜索指定距离内的文档
GET /shops/_search { "query": { // query查询 "bool": { // 布尔组合查询 "must": { "match_all": {} // 这里不设置其他查询条件,所以匹配全部文档 }, "filter": { // 【因为地理信息搜索不打算参与相关度计算,所以使用 filter 包裹 geo_distance】 "geo_distance": { // 【geo_distance 按距离搜索】 "distance": "1km", // 设置搜索距离为1千米 "location": { // 搜索location字段存储的经纬度和当前经纬度之间的距离。 "lat": 39.889916, // 当前纬度 "lon": 116.379547 // 当前经度 } } } } } }
如上,搜索当前经纬度和 location 字段存储的经纬度之间的距离在 1 千米范围之内的所有文档。
geo_distance参数说明:
- distance:设置搜索距离,常用距离单位:km(千米)、m(米)
- 当前经纬度坐标点:既然要计算距离,肯定需要知道两个坐标点才能计算,所以 geo_distance 参数需要提供当前坐标点。
按距离排序(_geo_distance)
根据地理信息搜索文档之后,返回多个文档数据的时候,很多业务场景都希望根据距离由近到远排序。
示例:
GET /shops/_search
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": { // 按距离搜索
"distance": "1km", // 搜索1千米范围
"location": { // 搜索字段为location
"lat": 39.889916, // 当前纬度
"lon": 116.379547 // 当前经度
}
}
}
}
},
"sort": [ // 设置排序条件
{
"_geo_distance": { //【 _geo_distance 代表根据距离排序】
"location": { // 根据location存储的经纬度计算距离。
"lat": 39.889916, // 当前纬度
"lon": 116.379547 // 当前经度
},
"order": "asc" // asc 表示升序,desc 表示降序
}
}
]
}
- 按距离排序条件,需要再次设置当前经纬度坐标,这样 ES 才知道计算距离的参考坐标。
按矩形范围搜索(geo_bounding_box)
ES 中通过 geo_bounding_box 搜索,在地图画一个矩形,搜索矩形范围内的坐标点。
示例:在地图画一个矩形,把矩形范围内的店铺找出来。
GET /shops/_search
{
"query": {
"bool": { // 布尔组合查询
"must": {
"match_all": {} // 这里设置其他搜索条件,直接搜索所有文档
},
"filter": { // 地理信息搜索不打算参与相关度评分,所以使用filter包裹起来。
"geo_bounding_box": { // geo_bounding_box实现按矩形范围搜索
"location": { // 店铺的坐标点保存在location字段中
"top_left": { // 【设置矩形的左上角坐标】
"lat": 40.73, // 纬度
"lon": -74.1 // 经度
},
"bottom_right": { // 【设置矩形的右下角坐标】
"lat": 40.717,
"lon": -73.99
}
}
}
}
}
},
"sort": [ // 设置排序条件
{
"_geo_distance": { // _geo_distance代表按距离排序
"location": { // 计算 location保存的坐标和当前坐标的距离
"lat": 40, // 当前纬度
"lon": -70 // 当前经度
},
"order": "asc" // 根据距离升序排序
}
}
]
}
- 按矩形范围搜索店铺,如果需要对搜索的结果按距离排序,需要指定一个当前参考坐标,否则 ES 无法计算距离,也就是无法按距离排序。
按多边形范围搜索(geo_polygon)
ES 通过 geo_polygon,在地图上画一个多边形,搜索包含在多边形内部的坐标点。
示例:在地图上画一个多边形,搜索店铺
GET /shops/_search
{
"query": {
"bool": {
"must": {
"match_all": {} // 这里不设置其他搜索条件,直接匹配所有文档
},
"filter": { // 地理信息搜索不参与相关度算分,所以使用filter包裹起来
"geo_polygon": { // geo_polygon 搜索语句
"location": { // 店铺的坐标存储在location字段.
"points": [ // 【设置组成多边形的经纬度坐标点数组】
{
"lat": 40.73, // 纬度
"lon": -74.1 // 经度
},
{
"lat": 40.83,
"lon": -75.1
},
{
"lat": 20,
"lon": -90
}
]
}
}
}
}
}
}
- 通常 ES 搜索中为了提升性能,可以使用 filter 禁掉相关度计算,还可以缓存查询结果。