一、背景
查询附近的洗车店
二、原理探究
像Redis和ES都支持GEO来存储地理位置。
GEO类型
- 地理点(geo_point),即经纬度查询,
- 地理形状查询(geo_shape),即支持点、线、圈、多边形查询
GeoHash
GeoHash 原理探究
Elasticsearch:理解 Elastic Maps 中的 geohash 及其聚合
Elasticsearch的默认等级是9,也就是精准到4.8米左右。
Elasticsearch官方并不建议我们修改精度,这可能会导致系统大幅度的变慢,在实际开发过程中,测试将精度等级调整至11级,查询多边形交叠数据返回时长高达4-8秒,难以应用生产环境。
三、实战
(1)创建索引
PUT my_location
{
"mappings": {
"properties": {
"location":{
"type": "geo_point"
}
}
}
}
(2)插入数据
数据范围要求:
- 纬度范围是-9090之间,经度范围是-180180之间。
- 经纬度数据都是浮点数或字符串
- 最大精度:小数点后7位。(常用小数点后6位即可。)
POST my_location/_bulk
{"index":{"_id":2}}
{"text":"上海站","location":{"lat":31.256224,"lon":121.462311}}
{"index":{"_id":3}}
{"text":"五一广场","location":"POINT (121.460186 31.251281)"}
{"index":{"_id":4}}
{"text":"交通公园","location":"31.253531,121.473939"}
{"index":{"_id":5}}
{"text":"万业远景大厦","location":[121.448215,31.26229]}
查询分为filter和query
- 使用query来搜索geo_point数据效率相对会慢一些。
- 建议使用filter来过滤geo_point数据
(3)查询(某个矩形框内)
GET /my_location/_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
}
}
}
}
}
}
}
(4)查询某个点附近 X 千米 - 附近搜索
pin就是指定当前的经纬度
distance是距离
geo_distance是圆圈的形式
GET my_location/_search
{
"query": {
"bool": {
"must": [
{"match_all": {}}
],
"filter": [
{
"geo_distance": {
"distance": "2000km",
"location": {
"lat": 40.73,
"lon": -74.1
}
}
}
]
}
}
}
(5)聚合分析 - 重点
- unit是距离单位,常用单位有:米(m),千米(km),英里(mi)
- distance_type是统计算法:sloppy_arc默认算法、arc最高精度、plane最高效率
GET /hotel_app/_doc/_search
{
"size": 0,// 这个意思是我不想看到统计的元数据信息
"aggs": { //统计
"agg_by_pin": { //统计的名字
"geo_distance": { //圆圈的形式做统计
"distance_type": "arc",//统计的类型 arc是最高精度 plane是最高效率
"field": "pin", //字段名
"origin": { // 原始的位置,就好比我用这个点做统计
"lat": 40,
"lon": -70
},
"unit": "mi", //指定单位是mi ,就是英里
"ranges": [ //根据范围统计
{ //距离0~80范围的
"to": 80
},
{ //80~300范围的数据
"from": 80,
"to": 300
},
{ // 300~1000范围的数据
"from": 300,
"to": 1000
}
]
}
}
}
}
四、参考链接&案例
【DSL】
附近的门店
ES7.16.2高级搜索之geo_point地理位置(四)
图灵学院 ElasticSearch课程
【GEO】
GeoHash实现
【JAVA API】
Springboot整合ES地理位置查询
【Redis】
spring-boot-redis-geo