elasticsearch地理位置查询
elasticsearch地理位置查询
一、背景
最近有个需求,需要获取某个位置附近的楼盘,**比如:**获取当前用户所在位置,方圆100km千米之内的楼盘信息。经过调研,发现可以使用 redis、mongodb、elasticsearch等实现。经过考虑之后决定使用es来实现,此处简单记录下es中geo方面api的使用。
二、geo数据类型
在es中存在2种地理位置数据类型,geo_point和geo_shape。es无法自动识别这种数据类型,需要在创建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个 arc和plane
arc:默认的方式,这种方式计算比较精确,但是比较慢,是把地球当作一个球体计算。plane:这种方式计算比较快,但是可能不怎么准,越靠近赤道越准,是把地球当成平坦的进行计算。
2、distance后面可用的单位有km、m、cm、mm、nmi、mi、yd、ft、in

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
}
}
}
}
四、参考文档
2、距离单位
3、排序
4、矩形查询
6、坐标拾取系统
elasticsearch地理位置查询的更多相关文章
- Java High Level REST Client 使用地理位置查询
Java High Level REST Client 使用地理位置查询 一.需求 二.对应的query语句 三.对应java代码 1.引入 jar 包 2.创建 RestHighLevelClien ...
- 【转】elasticsearch的查询器query与过滤器filter的区别
很多刚学elasticsearch的人对于查询方面很是苦恼,说实话es的查询语法真心不简单- 当然你如果入门之后,会发现elasticsearch的rest api设计是多么有意思. 说正题,ela ...
- 基于百度地图SDK和Elasticsearch GEO查询的地理围栏分析系统(1)
本文描述了一个系统,功能是评价和抽象地理围栏(Geo-fencing),以及监控和分析核心地理围栏中业务的表现. 技术栈:Spring-JQuery-百度地图WEB SDK 存储:Hive-Elast ...
- Elasticsearch Kibana查询语法
Elasticsearch Kibana查询语法 2018年06月03日 23:52:30 wangpei1949 阅读数:3992 Elasticsearch Kibana Discover的搜 ...
- MongoDB的地理位置查询,以及和mysql的使用对比
MongoDB的一个特色就是具有丰富的查询接口,比如地理位置查询. 在地理位置查询上,MongoDB有着比传统关系型数据库的优势,下面举个例子. 当前移动互联网应用,按用户离目标门店距离排序上的场景很 ...
- ElasticSearch—分页查询
ElasticSearch查询—分页查询详解 Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回.那么,如何实现分页查询呢? 按照一般的查询流程来说,如 ...
- Elasticsearch 邻近查询示例
Elasticsearch 邻近查询示例(全切分分词) JAVA API方式: SpanNearQueryBuilder span = QueryBuilders.spanNearQuery(); s ...
- elasticsearch简单查询
elasticsearch简单查询示例: { "from": "0", //分页,从第一页开始 "size": "10" ...
- ElasticSearch高级查询
ElasticSearch高级查询 https://www.imooc.com/video/15759/0 ElasticSearch查询 1,子条件查询:特定字段查询所指特定值 1.1query c ...
随机推荐
- 第09课:GDB 实用调试技巧(下)
本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...
- VUE003. 解决data中使用vue-i18n不更新视图问题(computed属性)
案例 在国际化开发中,有一部分需要国际化的文字是由数据驱动的储存在data中,然而VUE的data存在很多无法实时更新视图的问题,比如v-for循环的标签,当数据层次过深,通过源数据数组的索引改变它的 ...
- IDEA weblogic远程调试
weblogic远程调试 这里我们使用vulhub的镜像作为初始构建镜像搭建漏洞环境 1. 搭建docker环境 新建一个目录,创建两个文件 DockerFile FROM vulhub/weblog ...
- Java集合:HashMap
Hashmap是一个存储key-value的映射表. 优点: 索引数据快,查找一个数据对的时间复杂度是O(1) 增加.删除一个数据的时间复杂度是O(1) key不能重复,可以存储一个null值 存储: ...
- 通过Wireshark抓包分析谈谈DNS域名解析的那些事儿
文/朱季谦 本文主要想通过动手实际分析一下是如何通过DNS服务器来解析域名获取对应IP地址的,毕竟,纸上得来终觉浅,绝知此事要躬行. 域名与IP地址 当在浏览器上敲下"www.baidu.c ...
- three.js 材质翻转
刚学.这个鸟玩意儿卡了半天,记录一下. var skyBox = new THREE.Mesh(skyGeometry, skyMaterial); //创建一个完整的天空盒,填入几何模型和材质的参数 ...
- 基于 Vuex 的时移操作(撤回/恢复)实现
最近做了一个 BI 平台的可视化看板编辑器,项目刚做完一期,各方面的功能都还能粗糙,但该有的也都有了,比如编辑器场景下最基本的两类时移操作-撤回(undo) 和恢复 (redo). 用 vuex 实现 ...
- asp.net core使用identity+jwt保护你的webapi(一)——identity基础配置
前言 用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊.好在asp.net core给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不 ...
- android 使用SQLite的基本操作
Android操作数据库SQLite使用sql语句基本操作 1:自定义自己的SQLiteOpenHelper public class DBHelper extends SQLiteOpenHelpe ...
- 轻松集成腾讯云短信服务实现短信发送(Java实现)
不论是阿里云还是腾讯云,要想在网站上实现短信发送功能,首先得保证你的网站域名是通过备案的,因为短信签名是需要用到备案过的域名截图,所以域名通过了,申请很快就会审批成功了. (说点题外话,备案的话,需要 ...