最近有个需求是根据经纬度查询地图信息,刚开始有点懵懂,后来了解到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类型)相关推荐

  1. ElasticSearch查询学习笔记章节5——geo_distance,geo_bounding_box,geo_polygon地图检索geo查询

    ElasticSearch查询笔记目录   涉及的常用查询内容较多,将分多个章节进行笔记整理,具体如下: ElasticSearch查询学习笔记章节1--term,terms,match,id查询   ...

  2. ElasticSearch查询 第四篇:匹配查询(Match)

    <ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...

  3. elasticSearch -- (文档,类型,索引)

    问题:大规模数据如何检索 当系统数据量达到10亿,100亿级别的时候,我们系统该如何去解决这种问题. 数据库选择-mysql, sybase,oracle,mongodb,hbase- 单点故障如何解 ...

  4. Elasticsearch查询性能优化

    constant_score的用处 当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包 ...

  5. 【Elasticsearch】Elasticsearch 查询过程中的 pre-filter 原理

    1.概述 转载:添Elasticsearch 查询过程中的 pre-filter 原理 大家都知道在对索引执行查询的时候,需要在所有的分片上执行查询,因为无法知道被查询的关键词位于哪个分片,对于全文查 ...

  6. Go Elasticsearch 查询快速入门

    文章目录 0.前言 1.根据 ID 查询 2.精确匹配单个字段 3.精确匹配单个字段的多个值 4.全文查询 5.范围查询 6.判断某个字段是否存在 7.bool 组合查询 must filter sh ...

  7. 为什么Elasticsearch查询变得这么慢了?

    Elasticsearch 最少必要知识实战教程直播回放 0.引言 Elasticsearch社区中经常看到慢查询问题:"你能帮我看看Elasticsearch的响应时间吗?"或者 ...

  8. Elasticsearch:Elasticsearch 查询示例 - 动手练习(一)

    在我之前的文章文章: Elasticsearch:有用的 Elasticsearch 查询示例 开始使用 Elasticsearch (2) 我列举了很多关于 Elasticsearch 查询的例子. ...

  9. Elasticsearch入门教程(五):Elasticsearch查询(一)

    // 准备数据 PUT /shop/goods/1 {"name": "2017新款女装冬季外套ulzzang棉袄中长款棉衣韩版百搭棉服面包服","d ...

最新文章

  1. Linux进程间通信--信号
  2. sqlserver 新建只读权限用户
  3. 虚拟机共享文件夹引发的一点思考
  4. 分布式文件系统之Tachyon是什么?
  5. 读书笔记--对象、实例、原型、继承
  6. in python you can_Python编程:从入门到实践——【作业】——第十章(文件和异常)...
  7. 互联网项目管理流程(SOP)总结
  8. addLoadEvent方法解析
  9. Android 颜色表
  10. 判断浏览器内核是否是IE8及其以下
  11. HTML制作个简单的网页
  12. Ubuntu firefox无法加载视频
  13. 关于Id returned 1exit status的解决办法
  14. 比较IC卡、ID卡、M1卡、CPU卡它们之间有什么区别
  15. html图片绝对地址相对地址,HTML中background的图片地址是相对地址吗?
  16. 蓝牙鼠标windows linux,关于windows linux双系统共用蓝牙鼠标的教程
  17. 8个成语接龙首尾相连_四字成语接龙连接8个
  18. 时间复杂度的计算详解
  19. android小说模式,傲游Android版预读模式让手机小说控大饱眼福
  20. yocto,poky,qemu

热门文章

  1. C/C++编译器错误代码大全
  2. 百分之百还原《京东商城》项目实战1
  3. kubeadm创建k8s集群(1.14.2版本)
  4. 国内首本数据竞赛图书《阿里云天池大赛赛题解析——机器学习篇》今日开启预售!
  5. android设置不锁屏adb,如何通过ADB锁定Android屏幕?
  6. 商圈分析如何大数据软件采集相关要素
  7. xp系统为何无法登陆服务器,xp系统怎么登陆云服务器
  8. 南京大学计算机研究生复试面试题
  9. fast文件服务器的迁移,FastDfs数据迁移方案预研
  10. SQL count详细用法