redis实现坐标附近查询

源码:https://gitee.com/Jakewabc/small-study-case

根据经纬度搜索附近店铺,主要实现技术有redisMongoDBelasticsearch技术。这里就讲解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实现坐标附近查询相关推荐

  1. Redis 如何分析慢查询操作

    转载自  Redis 如何分析慢查询操作 什么是慢查询 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行 ...

  2. 面试突击 004 | 如何排查 Redis 中的慢查询?视频实战篇

    这是我的第 34 篇原创文章 作者 | 老王(javacn666) 1 面试题 如何排查 Redis 中的慢查询? 2 涉及相关问题 Redis 中有没有慢查询排查工具或者相关排查手段? 慢查询日志都 ...

  3. Redis 根据value 进行查询

    redis 根据value 进行查询 redis是一个key-value存储器,本身并没有提供相关根据value来进行模糊查询的方法,以下是在redis提供方法的基础上进行操作的,虽然效率低下,但是也 ...

  4. Redis的可视化工具查询内容为 --> “\xac\xed\x00\x05t\x00”乱码

    Redis的可视化工具查询内容为 --> "\xac\xed\x00\x05t\x00"乱码 1.简要描述 2.问题描述 3.采用String序列化时遇到的问题 4.解决问题 ...

  5. Redis存储对象条件查询(OLTP)

    Redis是key-value类型的内存数据库,通过key直接取数据虽然很方便,对于条件查询的支持远不如DB.虽然可以通过scan全表扫描,但比较麻烦也不够高效,于是通过以下方案简单处理一般情况的条件 ...

  6. SpringBoot简单集成Redis,实现简单查询

    1引入redis的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId& ...

  7. Redis使用场景一,查询出的数据保存到Redis中,下次查询的时候直接从Redis中拿到数据。不用和数据库进行交互。...

    maven使用: <!--redis jar包--><dependency><groupId>redis.clients</groupId><ar ...

  8. key redis 遍历_快乐运维Redis大数据量查询与清理

    一. keys命令(生产环境禁止使用) 简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代 ...

  9. redis 所有模糊key 查询_写完这篇Redis由浅入深剖析快自闭了!

    前言 常用的SQL数据库的数据都是存在磁盘中的,虽然在数据库底层也做了对应的缓存来减少数据库的IO压力,但由于数据库的缓存一般是针对查询的内容,而且粒度也比较小,一般只有表中的数据没有发生变动的时候, ...

最新文章

  1. 报错引发的版本对应——tensorflow+keras+python版本对应(全)
  2. 微信小程序会改变大世界吗?
  3. 够狠 | 单点登录三种方式,够狠!够劲爆!
  4. 5课件制作_【计算机论文】虚拟现实技术下多媒体课件开发的流程
  5. spring注册bean
  6. [Swift]LeetCode1049.最后一块石头的重量 II | Last Stone Weight II
  7. 物联网安全形势严峻——除严加管控外别无选择
  8. PostgreSQL ALTER TABLE 命令
  9. 车流量计数、不同车型统计算法
  10. 用C#开发.NET CF蓝牙通信模块
  11. forge不能用java打开_minecraft萌新官方启动器、forge、java常见问题
  12. Shell /dev/null 文件的含义
  13. laravel实现打包多个文件,并下载
  14. python批量爬取校花网图片
  15. android 呼入电话游戏闪退,光遇闪退解决方法 游戏总是闪退怎么回事
  16. PADS(7)——在PADS Layout一次性添加泪滴
  17. Open3d读写pcd点云文件
  18. 账号升级攻略:每天自动升级b站和网易云音乐,自动签到天翼云盘和百度贴吧...
  19. C# 求取圆心/球心坐标 ∈ C# 编程笔记
  20. CSS实现水波纹效果

热门文章

  1. Android 11 内置原生壁纸!速度来取
  2. springboot源码解析,kafkaredis面试题
  3. BOXI3 SDK 检索所有使用了某个universe object的报表
  4. Ubuntu14.04+cuda6.5+opencv2.4.9+caffe配置记录
  5. Alibaba内部首发“M8级”微服务架构手册,GitHub上杀疯了
  6. 为什么手机玩我的世界进服务器会显示红字,LOL进去时显示的蓝红标志是什么 | 手游网游页游攻略大全...
  7. Java中 [I@4554617c 问题解决
  8. php留言板留言界面
  9. ggplot2——饼图篇
  10. 【CF #797 Div3】A-E