一、背景

最近有个需求,需要获取某个位置附近的楼盘,**比如:**获取当前用户所在位置,方圆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、坐标拾取系统

elasticsearch地理位置查询的更多相关文章

  1. Java High Level REST Client 使用地理位置查询

    Java High Level REST Client 使用地理位置查询 一.需求 二.对应的query语句 三.对应java代码 1.引入 jar 包 2.创建 RestHighLevelClien ...

  2. 【转】elasticsearch的查询器query与过滤器filter的区别

    很多刚学elasticsearch的人对于查询方面很是苦恼,说实话es的查询语法真心不简单-  当然你如果入门之后,会发现elasticsearch的rest api设计是多么有意思. 说正题,ela ...

  3. 基于百度地图SDK和Elasticsearch GEO查询的地理围栏分析系统(1)

    本文描述了一个系统,功能是评价和抽象地理围栏(Geo-fencing),以及监控和分析核心地理围栏中业务的表现. 技术栈:Spring-JQuery-百度地图WEB SDK 存储:Hive-Elast ...

  4. Elasticsearch Kibana查询语法

    Elasticsearch Kibana查询语法 2018年06月03日 23:52:30 wangpei1949 阅读数:3992   Elasticsearch Kibana Discover的搜 ...

  5. MongoDB的地理位置查询,以及和mysql的使用对比

    MongoDB的一个特色就是具有丰富的查询接口,比如地理位置查询. 在地理位置查询上,MongoDB有着比传统关系型数据库的优势,下面举个例子. 当前移动互联网应用,按用户离目标门店距离排序上的场景很 ...

  6. ElasticSearch—分页查询

    ElasticSearch查询—分页查询详解 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如何实现分页查询呢? 按照一般的查询流程来说,如 ...

  7. Elasticsearch 邻近查询示例

    Elasticsearch 邻近查询示例(全切分分词) JAVA API方式: SpanNearQueryBuilder span = QueryBuilders.spanNearQuery(); s ...

  8. elasticsearch简单查询

    elasticsearch简单查询示例: { "from": "0", //分页,从第一页开始 "size": "10" ...

  9. ElasticSearch高级查询

    ElasticSearch高级查询 https://www.imooc.com/video/15759/0 ElasticSearch查询 1,子条件查询:特定字段查询所指特定值 1.1query c ...

随机推荐

  1. junit4 套件测试

    junit4 中的套件可以用来测试一个需要依赖的业务流程,如购买必须依赖与登录成功 代码实现: 测试数据存放 public class BaseTest { protected static Hash ...

  2. python模块--collections(容器数据类型)

    Counter类(dict的子类, 计数器) 方法 返回值类型 说明 __init__ Counter 传入可迭代对象, 会对对象中的值进行计数, 值为键, 计数为值 .elements() 迭代器 ...

  3. Tars | 第8篇 TarsJava Subset最终代码的执行流程与原理分析

    目录 前言 1. SubsetConf配置项的结构 1.1 SubsetConf 1.2 RatioConfig 1.3 KeyConfig 1.4 KeyRoute 1.5 SubsetConf的结 ...

  4. windows中对文件进行排序

    右键->排序方式->更多->选择需要的项目

  5. Vue个人博客关于标题自动打字机效果Typewriter

    最近在写个人Blog 中间看过很多个人博客的开发 一大部分用的是Hexo框架或者vuePress框架 导入各种主题样式插件等等 但是看多了就会发现 很多博主的个人博客基本都很相似 并没有什么新东西呈现 ...

  6. (超简单)VScode配置C/C++环境图文教程(Windows系统下)

    (超简单)VScode配置C/C++环境图文教程(Windows系统下) 本文参考文章 Visual Studio Code (vscode) 配置 C / C++ 环境 下载VScode.下载Min ...

  7. 超详细unittest单元测试框架总结

    unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果.今天笔者 ...

  8. 1.3redis小结--配置php reids拓展

    1.执行php文件 输出phpinfo();  <?php phpinfo(); 2.根据PHPinfo的信息确定需要下载的 php_redis.dll , php_igbinary.dll 版 ...

  9. Selenium自动化结合Mysql数据项目实战操作

    前言 web自动化结合Mysql做一些实战操作,今天实战的场景是通过读取web页面字段名与数据库相应的表中的字段名进行对比 - 注:商城是自己搭建在本地,小伙伴需要源码请私聊 解决思路 第一步:获取w ...

  10. Python读取ini配置文件(接口自动测试必备)

    前言 大家应该接触过.ini格式的配置文件.配置文件就是把一些配置相关信息提取出去来进行单独管理,如果以后有变动只需改配置文件,无需修改代码. 特别是后续做自动化的测试,代码和数据分享,进行管理.比如 ...