搜索引擎-应用篇(地理位置查询)

一、背景

查询附近的洗车店

二、原理探究

像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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机智的路易

用爱发电是走不远的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值