redis实现坐标附近查询
redis实现坐标附近查询
源码:https://gitee.com/Jakewabc/small-study-case
根据经纬度搜索附近店铺,主要实现技术有redis
、MongoDB
、elasticsearch
技术。这里就讲解redis
如何实现附近坐标搜索。
一、引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如果使用springboot
,那么这个依赖就不用指定版本号了。
二、位置信息操作
引入redis
操作模板
@Autowired
private RedisTemplate redisTemplate;
2.1、向redis添加单个位置
- 使用的方法
redisTemplate.boundGeoOps(K key).add(Point var1, M var2);
key
:集合名称
var1
:位置信息
var2
:位置名称
- 范例
// x:经度,Y:维度
Point point = new Point(106.63658, 26.653324);
// outlets 集合名称
redisTemplate.boundGeoOps("outlets").add(point, "这个位置的名称");
2.2、批量添加位置信息
- 使用的方法
redisTemplate.boundGeoOps(K key).add(Map<M, Point> var1);
key
:集合名称
var1
:是一个Map
集合,这个Map
集合的key
就是位置名称,value
保存Point
对象,这个对象就是保存经纬度信息的。
- 范例:
// 创建Map集合保存多个位置
Map<String,Point> map = new HashMap<>();
map.put("位置名称",new Point(106.777434,26.925769));
map.put("位置1",new Point(106.944735,26.888657));
map.put("位置2",new Point(106.623357,26.781373));
// 批量添加位置信息
redisTemplate.boundGeoOps("outlets").add(map);
2.3、根据位置名称查询坐标信息
- 使用的方法
redisTemplate.boundGeoOps(K key).position(M... var1);
key
:集合名称
M
:位置信息,可以传输多个。就是保存位置时保存的位置名称,保存位置的名称是什么类型,这里就是什么类型。
- 范例:
List<Point> position = redisTemplate.boundGeoOps("outlets").position("这个位置的名称");
System.out.println(position);
//输出: [Point [x=106.636581, y=26.653324]]List<Point> list = redisTemplate.boundGeoOps("outlets").position("位置名称", "位置1", "位置2");
System.out.println(list);
// 输入:[Point [x=106.777435, y=26.925769], Point [x=106.944735, y=26.888658], Point [x=106.623358, y=26.781373]]
2.4、计算两点间距离
- 使用方法
redisTemplate.boundGeoOps(K key).distance(M var1, M var2, Metric var3);
key
:集合名称
M
:位置信息,可以传输多个。就是保存位置时保存的位置名称,保存位置的名称是什么类型,这里就是什么类型。
var3
:返回距离的单位,默认为米。可以使用org.springframework.data.geo.Metrics
枚举类。Metrics.KILOMETERS
:千米
注意:distance(M var1, M var2, Metric var3);
如果只传var1
参数,不传 var3
参数,默认单位为米
- 范例:
// 直接这样计算,默认单位为 米M
Distance distance = redisTemplate.boundGeoOps("outlets").distance("位置1", "位置2");
// 计算两两点间的距离,并单位设置为千米。最后这个参数就是设置单位的。
Distance distance = redisTemplate.boundGeoOps("outlets").distance("位置1", "位置2", Metrics.KILOMETERS);
// 距离
double value = distance.getValue();
// 单位
String unit = distance.getUnit();
System.out.println("两地之间的距离:"+value+unit);
2.5、根据一个坐标查询附近位置
这个用途很广,也是存入坐标的最主要用途。给出当前地址,查询附近多少千米或者米的地点。
- 使用的方法
只返回坐标位置的名称,坐标信息没有返回的。
redisTemplate.boundGeoOps(K key).radius(Circle var1);
可以根据var2
配置返回值的信息。
redisTemplate.boundGeoOps(K key).radius(Circle var1, GeoRadiusCommandArgs var2);
var1
:设置当前经纬度坐标和需要查询附近多少距离和单位。
var2
:设置返回值的数据。
- 范例
这个只是看着有点多,其实思路非常简单。
// 指定经度和维度
Point point = new Point(106.6682, 26.896905);
// 指定距离和单位,目前是100千米km
Distance distance = new Distance(100, Metrics.KILOMETERS);
Circle circle = new Circle(point, distance);
// RedisGeoCommands.GeoLocation <String> 中的String 类型就是保存位置时填写的那个位置名称的数据类型
// .radius(circle); 只给 Circle 参数,那么只会返回一个网点名称,其余的参数都没有
// GeoResults<RedisGeoCommands.GeoLocation<String>> outlets = redisTemplate.boundGeoOps("outlets").radius(circle);// 指定返回的数据,当前这个点与附近这些点的距离
RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
args.sortAscending() // 升序排序// .sortDescending() // 降序排序.includeCoordinates() // 包含坐标信息信息.includeDistance() // 包含距离信息.limit(10); // 显示返回数量
// 根据坐标查询,并设置返回的参数
GeoResults<RedisGeoCommands.GeoLocation<String>> outlets = redisTemplate.boundGeoOps("outlets").radius(circle,args);
// 循环输出
for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : outlets){// 返回网点信息RedisGeoCommands.GeoLocation<String> location = result.getContent();// 网点名String name = location.getName();// 网点坐标Point point1 = location.getPoint();// 返回距离Distance dis = result.getDistance();// 距离double value = dis.getValue();// 单位String unit = dis.getUnit();// 输出System.out.println("网点名:"+ name + "x坐标"+point1.getX() + "y坐标" + point1.getY() + "距离:" + value + "单位:" + unit);
}
2.6、根据地点名称查询附近位置
这个和2.5
差不多,只是上面这个是根据一个经纬度坐标查询。而这个是根据地理位置名称查询,这个名称是添加位置的时候添加的名称。注意:如果查询的这个位置名称在redis
中不存在,那么是会包异常的。
- 使用方法
redisTemplate.boundGeoOps(K key).radius(M var1, Distance var2, GeoRadiusCommandArgs var3);
key
:集合名称
M
:位置名称,添加位置保存的那个名称。
var2
:设置距离和单位。
var3
:设置返回数据
独一无二的 上面是通过 Circle
对象指定坐标和距离。而这里是拆开设置,位置名称和距离信息,其余的一点都没有改变。
特别注意:这里的位置名称一定要存在,如果位置名称不存在就会报异常。org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR could not decode requested zset member
// 50 千米Distance distance = new Distance(50, Metrics.KILOMETERS);// 指定返回的数据,当前这个点与附近这些点的距离RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();args.sortAscending() // 升序排序
// .sortDescending() // 降序排序.includeCoordinates() // 包含坐标信息信息.includeDistance() // 包含距离信息.limit(10); // 显示返回数量// 根据坐标查询,并设置返回的参数// 只是 .radius("位置1",distance,args); 这里传输参数和testGeoRadius() 方法不同,其余全部一样。// 注意:查询这个名称一定要在集合中存在。如果不存在查询就会报异常 org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR could not decode requested zset memberGeoResults<RedisGeoCommands.GeoLocation<String>> outlets = redisTemplate.boundGeoOps("outlets").radius("位置2",distance,args);// 循环输出for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : outlets){// 返回网点信息RedisGeoCommands.GeoLocation<String> location = result.getContent();// 网点名String name = location.getName();// 网点坐标Point point1 = location.getPoint();// 返回距离Distance dis = result.getDistance();// 距离double value = dis.getValue();// 单位String unit = dis.getUnit();// 输出System.out.println("网点名:"+ name + "x坐标"+point1.getX() + "y坐标" + point1.getY() + "距离:" + value + "单位:" + unit);
// 50 千米Distance distance = new Distance(50, Metrics.KILOMETERS);// 指定返回的数据,当前这个点与附近这些点的距离RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();args.sortAscending() // 升序排序
// .sortDescending() // 降序排序.includeCoordinates() // 包含坐标信息信息.includeDistance() // 包含距离信息.limit(10); // 显示返回数量// 根据坐标查询,并设置返回的参数// 只是 .radius("位置1",distance,args); 这里传输参数和testGeoRadius() 方法不同,其余全部一样。// 注意:查询这个名称一定要在集合中存在。如果不存在查询就会报异常 org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR could not decode requested zset memberGeoResults<RedisGeoCommands.GeoLocation<String>> outlets = redisTemplate.boundGeoOps("outlets").radius("位置2",distance,args);// 循环输出for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : outlets){// 返回网点信息RedisGeoCommands.GeoLocation<String> location = result.getContent();// 网点名String name = location.getName();// 网点坐标Point point1 = location.getPoint();// 返回距离Distance dis = result.getDistance();// 距离double value = dis.getValue();// 单位String unit = dis.getUnit();// 输出System.out.println("网点名:"+ name + "x坐标"+point1.getX() + "y坐标" + point1.getY() + "距离:" + value + "单位:" + unit);
- 范例
// 50 千米
Distance distance = new Distance(50, Metrics.KILOMETERS);
// 指定返回的数据,当前这个点与附近这些点的距离
RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
args.sortAscending() // 升序排序// .sortDescending() // 降序排序.includeCoordinates() // 包含坐标信息信息.includeDistance() // 包含距离信息.limit(10); // 显示返回数量
// 根据坐标查询,并设置返回的参数
// 只是 .radius("位置1",distance,args); 这里传输参数和testGeoRadius() 方法不同,其余全部一样。
// 注意:查询这个名称一定要在集合中存在。如果不存在查询就会报异常 org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR could not decode requested zset member
GeoResults<RedisGeoCommands.GeoLocation<String>> outlets = redisTemplate.boundGeoOps("outlets").radius("位置2",distance,args);// 循环输出
for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : outlets){// 返回网点信息RedisGeoCommands.GeoLocation<String> location = result.getContent();// 网点名String name = location.getName();// 网点坐标Point point1 = location.getPoint();// 返回距离Distance dis = result.getDistance();// 距离double value = dis.getValue();// 单位String unit = dis.getUnit();// 输出System.out.println("网点名:"+ name + "x坐标"+point1.getX() + "y坐标" + point1.getY() + "距离:" + value + "单位:" + unit);
}
redis实现坐标附近查询相关推荐
- Redis 如何分析慢查询操作
转载自 Redis 如何分析慢查询操作 什么是慢查询 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行 ...
- 面试突击 004 | 如何排查 Redis 中的慢查询?视频实战篇
这是我的第 34 篇原创文章 作者 | 老王(javacn666) 1 面试题 如何排查 Redis 中的慢查询? 2 涉及相关问题 Redis 中有没有慢查询排查工具或者相关排查手段? 慢查询日志都 ...
- Redis 根据value 进行查询
redis 根据value 进行查询 redis是一个key-value存储器,本身并没有提供相关根据value来进行模糊查询的方法,以下是在redis提供方法的基础上进行操作的,虽然效率低下,但是也 ...
- Redis的可视化工具查询内容为 --> “\xac\xed\x00\x05t\x00”乱码
Redis的可视化工具查询内容为 --> "\xac\xed\x00\x05t\x00"乱码 1.简要描述 2.问题描述 3.采用String序列化时遇到的问题 4.解决问题 ...
- Redis存储对象条件查询(OLTP)
Redis是key-value类型的内存数据库,通过key直接取数据虽然很方便,对于条件查询的支持远不如DB.虽然可以通过scan全表扫描,但比较麻烦也不够高效,于是通过以下方案简单处理一般情况的条件 ...
- SpringBoot简单集成Redis,实现简单查询
1引入redis的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId& ...
- Redis使用场景一,查询出的数据保存到Redis中,下次查询的时候直接从Redis中拿到数据。不用和数据库进行交互。...
maven使用: <!--redis jar包--><dependency><groupId>redis.clients</groupId><ar ...
- key redis 遍历_快乐运维Redis大数据量查询与清理
一. keys命令(生产环境禁止使用) 简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代 ...
- redis 所有模糊key 查询_写完这篇Redis由浅入深剖析快自闭了!
前言 常用的SQL数据库的数据都是存在磁盘中的,虽然在数据库底层也做了对应的缓存来减少数据库的IO压力,但由于数据库的缓存一般是针对查询的内容,而且粒度也比较小,一般只有表中的数据没有发生变动的时候, ...
最新文章
- 报错引发的版本对应——tensorflow+keras+python版本对应(全)
- 微信小程序会改变大世界吗?
- 够狠 | 单点登录三种方式,够狠!够劲爆!
- 5课件制作_【计算机论文】虚拟现实技术下多媒体课件开发的流程
- spring注册bean
- [Swift]LeetCode1049.最后一块石头的重量 II | Last Stone Weight II
- 物联网安全形势严峻——除严加管控外别无选择
- PostgreSQL ALTER TABLE 命令
- 车流量计数、不同车型统计算法
- 用C#开发.NET CF蓝牙通信模块
- forge不能用java打开_minecraft萌新官方启动器、forge、java常见问题
- Shell /dev/null 文件的含义
- laravel实现打包多个文件,并下载
- python批量爬取校花网图片
- android 呼入电话游戏闪退,光遇闪退解决方法 游戏总是闪退怎么回事
- PADS(7)——在PADS Layout一次性添加泪滴
- Open3d读写pcd点云文件
- 账号升级攻略:每天自动升级b站和网易云音乐,自动签到天翼云盘和百度贴吧...
- C# 求取圆心/球心坐标 ∈ C# 编程笔记
- CSS实现水波纹效果
热门文章
- Android 11 内置原生壁纸!速度来取
- springboot源码解析,kafkaredis面试题
- BOXI3 SDK 检索所有使用了某个universe object的报表
- Ubuntu14.04+cuda6.5+opencv2.4.9+caffe配置记录
- Alibaba内部首发“M8级”微服务架构手册,GitHub上杀疯了
- 为什么手机玩我的世界进服务器会显示红字,LOL进去时显示的蓝红标志是什么 | 手游网游页游攻略大全...
- Java中 [I@4554617c 问题解决
- php留言板留言界面
- ggplot2——饼图篇
- 【CF #797 Div3】A-E