ElasticSearch查询地图信息(geo-point类型)
最近有个需求是根据经纬度查询地图信息,刚开始有点懵懂,后来了解到es里有个geo-point的类型,这个是存放地理坐标点的信息也就是经纬度的信息,然后通过点位查询距离范围内也就是一个圆内的所有数据。
设置数据格式
地理坐标点(geo-point) 是指地球表面可以用经纬度描述的一个点。地理坐标点可以用来计算两个坐标位置间的距离,或者判断一个点是否在一个区域中。地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo_point ,例子中的es mapping只有location字段
{"properties": {"location": {"type": "geo_point"}}
}
半角逗号分割的字符串形式 “lat,lon“
明确以 lat 和 lon 作为属性的对象
数组形式表示 [lon,lat]
需要特别注意的就是纬度在前边经度在后边(latitude,longitude),数组表示形式是经度在前纬度在后([longitude,latitude])
这里作者使用的是作者存的值是"location" : "25.004,102.704"的字符串类型,纬度在前,经度在后
geo_distance 找出指定位置在给定距离内的数据,相当于指定圆心和半径找到圆中点
找出distance范围内的所有点位信息
distance:距离 单位/m
location:坐标点 圆心所在位置
/*** 查询地图信息* @author Songsong* @param latitude 纬度* @param longitude 经度* @param distance 距离/单位:m* @param esIndex es索引* @param t 返回类型* @return java.util.List<T>* @date 2020-11-17 21:27*/public <T> List<T> queryMapData(String latitude, String longitude, Integer distance, String esIndex, Class<T> t) {//筛选坐标指定范围内的数据GeoDistanceQueryBuilder distanceQueryBuilder =QueryBuilders.geoDistanceQuery("location").point(Double.parseDouble(latitude), Double.parseDouble(longitude)).distance(distance, DistanceUnit.METERS).geoDistance(GeoDistance.PLANE);SearchRequest searchRequest = new SearchRequest();//查询条件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().filter(distanceQueryBuilder);searchSourceBuilder.query(queryBuilder);searchSourceBuilder.from(0);searchSourceBuilder.size(10000);//按照距离排序GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("location",new GeoPoint(Double.parseDouble(latitude), Double.parseDouble(longitude))).order(SortOrder.ASC).unit(DistanceUnit.METERS).geoDistance(GeoDistance.PLANE);searchSourceBuilder.sort(sortBuilder);searchRequest.source(searchSourceBuilder);searchRequest.indices(esIndex);List<T> result = new ArrayList<>();try {SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);SearchHits searchHits = searchResponse.getHits();SearchHit[] searchHitArray = searchHits.getHits();for (SearchHit searchHit : searchHitArray) {//下划线转驼峰result.add(CamelAndUnderlineUtil.underlineToCamel(searchHit.getSourceAsString(), t));}} catch (IOException e) {log.error("Method:queryMapData,es查询异常:{}", e.getMessage());}return result;}
CamelAndUnderlineUtil.underlineToCamel这个方法参考作者之前写的
java实用型-驼峰下划线互转
以上java代码是根据经纬度查询distance范围内的数据,返回结果是入参中的对象list,结构可以自己定义。
以上最大查询条数为1w条,并且是按照距离中心点升序后的数据,如果想返回更多的数据怎么办,这时候我们可以考虑用scroll查询,每次根据最新的scroll_id去查询,然后封装到一起再返回,这样可以达到返回>1w的数据的效果。
一、什么是游标查询(Scroll)
顾名思义,相当于用一把游标标记查询的位置.
二.、为什么要使用游标查询
在默认情况下,ES查询每次返回的数量最多只有1W条,且只能是前1W条.
这意味着,在不修改配置的情况下,想通过分页的方式(如下)拿到1W条之后的数据是做不到的,所以自然就有了游标查询。
三、如何使用游标查询
DSL的用法:
复制代码
GET 索引/类型/_search?scroll=1m
{
“size”: 10000,
“query”: {
“match_all”: {}
}
}
复制代码
1m表示:过期时间1分钟
查询结果的第一行会有:
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBAAAAAAABO-dFmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7J_hYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC- SmQWWk1aN0sxUmRSQmFNS3EwVFh0R0luUQAAAAAAvkplFlpNWjdLMVJkUkJhTUtxMFRYdEdJblE=",
这个_scroll_id就相当于书签,之后的查询带着这个书签,就能根据size不断拿到之后的数据,但是前提是在过期时间之内
之后的查询DSL:
GET _search/scroll
{"scroll":"1m","scroll_id":"DnF1ZXJ5VGhlbkZldGNoBAAAAAAABPP1FmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7OTxYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-j70WVVlOZkxQRzJRLXlMRlVMbEQtalBfUQAAAAAAyWm-Fk9HdGx1b3VsUXRLZHV4c1E1OExja0E="
}
将获取的scroll_id作为条件继续查询即可,这里不需要再指定索引和类型,因为scroll_id的唯一性.
在过期时间内,之后的查询的scroll_id是不变的.
示例:比如返回5w条数据,每次查询5000条,也就是说总共需要查10次,不多说,上java代码:
/*** 查询地图信息* @author Songsong* @param latitude 纬度* @param longitude 经度* @param distance 距离/单位:m* @param esIndex es索引* @param t 返回类型* @return java.util.List<T>* @date 2020-11-17 21:27*/
public <T> List<T> queryMapData(String latitude, String longitude, Integer distance, String esIndex, Class<T> t) {//筛选坐标指定范围内的数据GeoDistanceQueryBuilder distanceQueryBuilder =QueryBuilders.geoDistanceQuery("location").point(Double.parseDouble(latitude), Double.parseDouble(longitude)).distance(distance, DistanceUnit.METERS).geoDistance(GeoDistance.PLANE);SearchRequest searchRequest = new SearchRequest();//查询条件SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().filter(distanceQueryBuilder);searchSourceBuilder.query(queryBuilder);searchSourceBuilder.from(0);searchSourceBuilder.size(5000);//scoll滚动查询Scroll scroll = new Scroll((TimeValue.timeValueMinutes(1L)));//按照距离排序GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("location",new GeoPoint(Double.parseDouble(latitude), Double.parseDouble(longitude))).order(SortOrder.ASC).unit(DistanceUnit.METERS).geoDistance(GeoDistance.PLANE);searchSourceBuilder.sort(sortBuilder);searchRequest.source(searchSourceBuilder);searchRequest.indices(esIndex);searchRequest.scroll(scroll);List<T> result = new ArrayList<>();try {SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);SearchHits searchHits = searchResponse.getHits();SearchHit[] searchHitArray = searchHits.getHits();String scrollId = searchResponse.getScrollId();//限制返回最大数量while (null != searchHitArray && searchHitArray.length > 0 && result.size() < 50000) {for (SearchHit searchHit : searchHitArray) {//下划线转驼峰result.add(CamelAndUnderlineUtil.underlineToCamel(searchHit.getSourceAsString(), t));}//构造滚动查询条件SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);searchScrollRequest.scroll(scroll);searchResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);scrollId = searchResponse.getScrollId();searchHitArray = searchResponse.getHits().getHits();}//处理完成后清除滚动ClearScrollRequest clearScrollRequest = new ClearScrollRequest();clearScrollRequest.addScrollId(scrollId);restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);} catch (IOException e) {log.error("Method:queryMapData,es查询异常:{}", e.getMessage());}return result;}
CamelAndUnderlineUtil.underlineToCamel这个方法参考作者之前写的
java实用型-驼峰下划线互转
以上就是根据最新的scroll_id查询下一页的数据,此查询有个弊端,就是不能查询指定的页数,每次只能查询下一页的数据,所以具体得看使用场景。
所有数据获取完毕之后,需要手动清理掉 scroll_id 。虽然es 会有自动清理机制,但是 srcoll_id 的存在会耗费大量的资源来保存一份当前查询结果集映像,并且会占用文件描述符。所以用完之后要及时清理。所以就有了这段代码:
//处理完成后清除滚动
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
进行手动清理scroll_id的操作。
ElasticSearch查询地图信息(geo-point类型)相关推荐
- ElasticSearch查询学习笔记章节5——geo_distance,geo_bounding_box,geo_polygon地图检索geo查询
ElasticSearch查询笔记目录 涉及的常用查询内容较多,将分多个章节进行笔记整理,具体如下: ElasticSearch查询学习笔记章节1--term,terms,match,id查询 ...
- ElasticSearch查询 第四篇:匹配查询(Match)
<ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...
- elasticSearch -- (文档,类型,索引)
问题:大规模数据如何检索 当系统数据量达到10亿,100亿级别的时候,我们系统该如何去解决这种问题. 数据库选择-mysql, sybase,oracle,mongodb,hbase- 单点故障如何解 ...
- Elasticsearch查询性能优化
constant_score的用处 当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包 ...
- 【Elasticsearch】Elasticsearch 查询过程中的 pre-filter 原理
1.概述 转载:添Elasticsearch 查询过程中的 pre-filter 原理 大家都知道在对索引执行查询的时候,需要在所有的分片上执行查询,因为无法知道被查询的关键词位于哪个分片,对于全文查 ...
- Go Elasticsearch 查询快速入门
文章目录 0.前言 1.根据 ID 查询 2.精确匹配单个字段 3.精确匹配单个字段的多个值 4.全文查询 5.范围查询 6.判断某个字段是否存在 7.bool 组合查询 must filter sh ...
- 为什么Elasticsearch查询变得这么慢了?
Elasticsearch 最少必要知识实战教程直播回放 0.引言 Elasticsearch社区中经常看到慢查询问题:"你能帮我看看Elasticsearch的响应时间吗?"或者 ...
- Elasticsearch:Elasticsearch 查询示例 - 动手练习(一)
在我之前的文章文章: Elasticsearch:有用的 Elasticsearch 查询示例 开始使用 Elasticsearch (2) 我列举了很多关于 Elasticsearch 查询的例子. ...
- Elasticsearch入门教程(五):Elasticsearch查询(一)
// 准备数据 PUT /shop/goods/1 {"name": "2017新款女装冬季外套ulzzang棉袄中长款棉衣韩版百搭棉服面包服","d ...
最新文章
- Linux进程间通信--信号
- sqlserver 新建只读权限用户
- 虚拟机共享文件夹引发的一点思考
- 分布式文件系统之Tachyon是什么?
- 读书笔记--对象、实例、原型、继承
- in python you can_Python编程:从入门到实践——【作业】——第十章(文件和异常)...
- 互联网项目管理流程(SOP)总结
- addLoadEvent方法解析
- Android 颜色表
- 判断浏览器内核是否是IE8及其以下
- HTML制作个简单的网页
- Ubuntu firefox无法加载视频
- 关于Id returned 1exit status的解决办法
- 比较IC卡、ID卡、M1卡、CPU卡它们之间有什么区别
- html图片绝对地址相对地址,HTML中background的图片地址是相对地址吗?
- 蓝牙鼠标windows linux,关于windows linux双系统共用蓝牙鼠标的教程
- 8个成语接龙首尾相连_四字成语接龙连接8个
- 时间复杂度的计算详解
- android小说模式,傲游Android版预读模式让手机小说控大饱眼福
- yocto,poky,qemu