Elasticsearch ES实现GEO位置搜索

ES实现GEO位置搜索

Elasticsearch-7.15.2
附近查询,也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。

创建索引 (my_geo),直接设置mapping

GEO字段的创建:添加一个字段location,类型为 geo_point。

GEO类型的字段是不能使用动态映射自动生成的,我们需要在创建索引时指定字段的类型为geo_point,geo_point 类型的字段存储的经纬度。

curl -X PUT http://192.168.11.21:9200/my_geo -H 'Content-Type:application/json' -d'
{"mappings": {"properties": {"name": {"type": "text"},"location": {"type":"geo_point"}}}
}'

插入2条数据

curl -X POST 192.168.11.21:9200/my_geo/_doc/1 -H 'Content-Type: application/json' -d '{"name": "路人甲北京站","location": {"lat": 39.90279998006104,"lon": 116.42703999493406}
}'curl -X POST 192.168.11.21:9200/my_geo/_doc/2 -H 'Content-Type: application/json' -d '{"name": "路人乙朝阳公园","location": {"lat": 39.93367367974064,"lon": 116.47845257733152}
}'
查询语句 curl

我的位置在“工体”,“北京站”的路人甲和“朝阳公园”的路人乙都在5km的范围内,查询5km和3km范围内都有谁。

把范围缩短distance改为3km,请求如下:

curl -XGET '192.168.11.21:9200/my_geo/_search?pretty=true' -H 'Content-Type:application/json' -d '
{"query":{"bool":{"must":{"match_all":{ }},"filter":{"geo_distance":{"distance":"3km","location":{"lat": 39.93031708627304,"lon": 116.4470385453491}}}}}}'

结果:在“朝阳公园”的路人乙被搜索了出来。

{"took" : 4,"timed_out" : false,"_shards" : {"total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0},"hits" : {"total" : { "value": 1, "relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "my_geo","_type" : "_doc","_id" : "2","_score" : 1.0,"_source" : {"name" : "路人乙朝阳公园","location" : {"lat" : 39.93367367974064,"lon": 116.47845257733152}}}]}}

距离排序

5公里范围内排序查询。

curl -XGET  'http://192.168.11.21:9200/my_geo/_search?pretty=true' -H 'Content-Type:application/json' -d '
{"query":{"bool":{"must":{"match_all":{ }},"filter":{"geo_distance":{ // 按距离搜索"distance":"5km", // 搜索范围"location":{"lat": 39.93031708627304,"lon": 116.4470385453491} // 当前纬度 经度}}}},"sort": [{"_geo_distance": { // _geo_distance代表根据距离排序"location": { // 根据location存储的经纬度计算距离"lat": 39.93031708627304, // 当前纬度 经度"lon": 116.4470385453491},"order": "asc"}}]
}' 

curl查询结果:离我“工体”比较近的“路人乙”排在了第一个,也是符合预期的。

{"took" : 10,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : null,"hits" : [{"_index" : "my_geo","_type" : "_doc","_id" : "2","_score" : null,"_source" : {"name" : "路人乙","location" : {"lat" : 39.93367367974064,"lon" : 116.47845257733152}},"sort" : [2704.400492813901]},{"_index" : "my_geo","_type" : "_doc","_id" : "1","_score" : null,"_source" : {"name" : "路人甲","location" : {"lat" : 39.90279998006104,"lon" : 116.42703999493406}},"sort" : [3503.0165324004943]}]}}

JAVA程序中使用GEO搜索

在定义实体类时,对应的GEO字段要使用特殊的类型。location的类型是GeoPoint,添加数据时转成Json存储。

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;@Data
@Document(indexName = "my_geo")
public class MyGeo {@Field(type = FieldType.Keyword)private String goodsName;@Field(store = true)@GeoPointFieldprivate GeoPoint location;
}

geo距离查询

    public void geoDistanceQuery(){//创建查询请求对象SearchRequest request = new SearchRequest("my_geo");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();GeoPoint geoPoint = new GeoPoint(39.93031708627304, 116.4470385453491);//工体的坐标//geo距离查询QueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location").distance(5, DistanceUnit.KILOMETERS).point(geoPoint);sourceBuilder.query(queryBuilder);request.source(sourceBuilder);try {SearchResponse response = client.search(request, RequestOptions.DEFAULT);for(SearchHit hit : response.getHits().getHits()){System.out.println(hit.getSourceAsString());}}catch (Exception e){e.printStackTrace();}}
结果:
{"name":"路人甲","location":{"lat":39.90279998006104,"lon":116.42703999493406}}
{"name":"路人乙","location":{"lat":39.93367367974064,"lon":116.47845257733152}}

距离排序

    public void geoDistanceSortQuery(){SearchRequest request = new SearchRequest("my_geo"); //创建查询请求对象SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();GeoPoint geoPoint = new GeoPoint(39.93031708627304, 116.4470385453491);//工体的坐标GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("location", geoPoint).order(SortOrder.ASC);sourceBuilder.sort(sortBuilder);request.source(sourceBuilder);SearchResponse response = client.search(request, RequestOptions.DEFAULT);for(SearchHit hit : response.getHits().getHits()){System.out.println(hit.getSourceAsString());}
结果:
{"name":"路人乙","location":{"lat":39.93367367974064,"lon":116.47845257733152}}
{"name":"路人甲","location":{"lat":39.90279998006104,"lon":116.42703999493406}}

其他

距离排序(带分页)
GeoDistanceQueryBuilder

    /***  ElasticSearchRepository和 RestHighLevelClient ElasticsearchRestTemplate的区别*  https://blog.csdn.net/zhiyikeji/article/details/128908596**  从名字就能看出来,QueryBuilder主要用来构建查询条件、过滤条件,SortBuilder主要是构建排序。*  譬如,我们要查询距离某个位置100米范围内的所有人、并且按照距离远近进行排序:*/public void findGeoDistanceSort(){double lat = 39.93031708627304, lng = 116.4470385453491; //工体//设定搜索半径GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location")//.geoDistance(GeoDistance.PLANE).point(lat, lng).distance(300, DistanceUnit.KILOMETERS);//计算距离多少公里 获取点与点之间的距离GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("location", lat, lng).point(lat, lng).unit(DistanceUnit.METERS).order(SortOrder.ASC);Pageable pageable = PageRequest.of(0, 10);NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder().withPageable(pageable).withFilter(queryBuilder).withSort(sortBuilder);NativeSearchQuery nativeSearchQuery = builder.build();org.springframework.data.elasticsearch.core.SearchHits<MyGeo> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, MyGeo.class);List<org.springframework.data.elasticsearch.core.SearchHit<MyGeo>> searchHitList = searchHits.getSearchHits();if(searchHitList.isEmpty()){System.out.println("没有查询到数据!");return;}searchHitList.forEach(hit ->{// 此处的索引和查询返回结果中sort集合的索引一致,目的在于取返回结果中的距离计算结果,以免二次计算,造成资源浪费//Object geoDistance = hit.getSortValues().get(2);System.out.println("hit -- " + JSONObject.toJSONString(hit));});}结果:
{"name":"路人乙","location":{"lat":39.93367367974064,"lon":116.47845257733152}}
{"name":"路人甲","location":{"lat":39.90279998006104,"lon":116.42703999493406}}

参考资料

ES7学习笔记(十三)GEO位置搜索
https://www.modb.pro/db/73991

ES GEO地理空间查询 基于geo-point的多边形查询
https://huaweicloud.csdn.net/637eedd2df016f70ae4c9b19.html

通过ElasticsearchRestTemplate 完成地理搜索 矩形搜索,附近人搜索, 距离搜索
https://blog.csdn.net/qq_41712271/article/details/134881584

###复杂查询包含ES按距离排序
https://blog.csdn.net/m0_56726104/article/details/120785048


geo 距离排序检索
https://blog.csdn.net/wenxingchen/article/details/95448215/

GEO位置搜索 https://www.modb.pro/db/73991
ElasticsearchTemplate 经纬度按距离排序 http://www.javashuo.com/article/p-uqiafsey-hx.html

ES 位置查询之geo_point
https://blog.csdn.net/weixin_43918355/article/details/118366065

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/619548.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes 集群管理—日志架构

日志架构 应用日志可以让你了解应用内部的运行状况。日志对调试问题和监控集群活动非常有用。 大部分现代化应用都有某种日志记录机制。同样地&#xff0c;容器引擎也被设计成支持日志记录。 针对容器化应用&#xff0c;最简单且最广泛采用的日志记录方式就是写入标准输出和标…

必练的100道C语言程序设计练习题(上)

前言: 在计算机编程的世界中&#xff0c;C语言一直是一门备受推崇的语言。它的简洁性、高效性以及广泛应用使得学习C语言成为每一位程序员的必由之路。然而&#xff0c;掌握这门语言并不是一蹴而就的事情&#xff0c;它需要不断的练习和实践。为了帮助各位编程爱好者更好地理解…

整合junit与热部署

整合junit <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.7.0</version></dependency> 测试类上添加SpringBootTest 如&#xff1a; 注意测试类的…

计算机组成原理 CPU的功能和基本结构和指令执行过程

文章目录 CPU的功能和基本结构CPU的功能CPU的基本结构 指令执行过程指令周期概念指令执行方案指令数据流取周期数据流析指周期数据流执行周期数据流中断周期数据流 数据通路的功能和基本结构数据通路的功能数据通路的结构单总线 CPU的功能和基本结构 #mermaid-svg-jr0QOEyC6Q92…

微服务治理:微服务断路器(微服务故障隔离模式)详解

微服务断路器是一种设计模式&#xff0c;可以保护系统免于级联故障&#xff0c;通过限制对故障服务的调用来实现。它的工作原理类似于电气断路器&#xff1a;当服务遇到问题时&#xff0c;它会切断请求流&#xff0c;使其有机会恢复&#xff0c;并防止其他服务被压垮。 工作原…

透过历史的琉璃之窗:古代玻璃制品成分解析--2022年国赛C题获奖论文思考

问题一&#xff1a;数据预处理------>剔除处理无效数据 转化完美成分数据----定和为1 中心化对数比变换------消除定和限制对后续分析的影响 类别量化分析相关性 第1小问------对超过20%的比例期望计数小于5的组别---------Pearson卡方检验法 对不满足卡方前提的组别----…

使用numpy处理图片——分离通道

大纲 读入图片分离通道堆叠法复制修改法 生成图片 在《使用numpy处理图片——滤镜》中&#xff0c;我们剥离了RGB中的一个颜色&#xff0c;达到一种滤镜的效果。 如果我们只保留一种元素&#xff0c;就可以做到PS中分离通道的效果。 读入图片 import numpy as np import PIL.…

51-10 多模态论文串讲—ALBEF 论文精读

今天我们就来过一下多模态的串讲&#xff0c;其实之前&#xff0c;我们也讲了很多工作了&#xff0c;比如说CLIP&#xff0c;还有ViLT&#xff0c;以及CLIP的那么多后续工作。多模态学习在最近几年真的是异常的火爆&#xff0c;那除了普通的这种多模态学习&#xff0c;比如说视…

自动化神器 Playwright 的 Web 自动化测试解决方案

1. 主流框架的认识 总结&#xff1a; 由于Selenium在3.x和4.x两个版本的迭代中并没有发生多大的变化&#xff0c;因此Selenium一统天下的地位可能因新框架的出现而变得不那么稳固。后续的Cypress、TestCafe、Puppeteer被誉为后Selenium时代Web UI自动化的三驾马车。但是由于这三…

逼格满满,推荐一个高效测试用例工具:XMind2TestCase !

一、背景 软件测试的核心是什么&#xff1f;毫无疑问是测试分析和测试用例设计&#xff0c;也是日常测试投入最多时间的工作内容之一。 然而&#xff0c;传统的测试用例设计过程有很多痛点&#xff1a; 1、使用Excel表格进行测试用例设计&#xff0c;虽然成本低&#xff0c;但…

NeRF算法模型简析:从理论到实践的轻度解析以及如何编辑和微调

nerf模型可编辑的&#xff1f; NeRF模型的可编辑性&#xff08;editability&#xff09;指的是能够修改预训练的NeRF模型以改变其生成的场景或对象的某些特征&#xff0c;而不是从头开始重新训练模型。这种编辑可以是改变颜色、形状、纹理或者添加、移除和修改场景中的对象。 在…

java应用CPU过高查找原因

用top查到占用cpu最高的进程pid 根据进程ID找到占用CPU高的线程 ps -mp 60355 -o THREAD,tid | sort -r 用 printf "%x \n" 将tid换为十六进制&#xff1a;xid printf "%x \n" 6036 根据16进制格式的线程ID查找线程堆栈信息 jstack 60355 |grep ebcb -A…

Open3D 从点云构建八叉树(13)

Open3D 从点云构建八叉树(13) 一、什么是八叉树二、构建方法三、实际作用四、算法实现1.代码2.可视化显示一、什么是八叉树 八叉树(Octree) 是什么: 八叉树(Octree)是一种树形数据结构,通常用于对三维空间进行分割和组织。它将空间递归地划分为立方体的8个子块,每个子…

Python装饰器管理类和函数

1 Python装饰器管理类和函数 Python装饰器可以管理函数和实例的调用&#xff0c;也可以直接管理函数和类本身。 1.1 装饰器将函数和类保存到字典 描述 通过装饰器将函数或类保存到字典&#xff0c;以便后续使用。 &#xff08;1&#xff09; 定义一个字典&#xff1b; &a…

【linux驱动开发】在linux内核中注册一个杂项设备与字符设备以及内核传参的详细教程

文章目录 注册杂项设备驱动模块传参注册字符设备 开发环境&#xff1a; windows ubuntu18.04 迅为rk3568开发板 注册杂项设备 相较于字符设备&#xff0c;杂项设备有以下两个优点: 节省主设备号:杂项设备的主设备号固定为 10&#xff0c;在系统中注册多个 misc 设备驱动时&…

【分布式技术】监控平台zabbix自定义模板、设置邮件报警、导入模板

目录 案例&#xff1a;监控当前登录人数&#xff0c;超过3人触发报警发送邮件 第一步&#xff1a;自定义模板 1、明确想要获取监控数据的命令和脚本 ​编辑 2、在被监控主机上&#xff0c;修改zabbix agent2的配置文件或者在zabbix agent2的配置文件目录中添加以.conf结尾…

三棋先手必胜证明

目录 创作原因 游戏规则 初始状态图 证明过程 先手必胜的证明 失败的博弈树&#xff08;三个多小时的成果&#xff09; 创作原因 这个棋不是网上流行的成三棋&#xff0c;我也不知道这个棋叫什么。由于这个棋是&#xff08;横竖斜&#xff09;连成三个就获胜&#xff0c;…

GBASE南大通用数据库如何检索单行

SELECT 语句返回的行集是它的活动集。单个 SELECT 语句返回单个行。您可使用嵌入式 SELECT 语句来从数据库将单个行检索到主变量内。然而&#xff0c;当 SELECT 语句返回多行数 据时&#xff0c;程序必须使用游标来一次检索一行。在 检索多行 中讨论“多行”选择操作。 要检索单…

虹软人脸识别白屏

1.修改jdk为1.8 2.编译版本ndk修改 ndk {abiFilters armeabi-v7a, arm64-v8a} 3.local.properties增加ndk路径 ndk.dirH\:\\Android\\SDK\\ndk\\21.1.6352462 4.最重要的一步:检查依赖库是否存在前一定要先检查有么有读取本地文件权限,下面的代码即使是放到点击事件的回调…

[AutoSar]BSW_OS 01 Autosar OS入门(一)

目录 关键词平台说明一、Autosar OS 的位置二、Autosar OS 与OSEK三、TASK 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C&#xff0c;C编译器HighTec (GCC) 一、Autosar OS 的位置 如在[AutoSar]基础部分 a…