上篇文章(Redis地理算法GEO解析和应用)我们对redis GEO算法进行解析以及相关shell命令的使用,这篇文章将带你进行实战应用。

依赖

注:jedis可以不引入,这里只是为了方便查看源码进行解析

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.3.0.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/redis.clients/jedis --><!--     方便查看源码   --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.3.0</version></dependency>

数据源配置

spring:redis:host: localhostport: 6379database: 4

编写实例

package com.gmall.user.server;import com.gamll.user.base.BaseJunitTest;
import com.gmall.user.server.biz.UserBiz;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author HL.Wu* @date 2020/5/28 17:54* Copyright ©https://blog.csdn.net/qq_31150503 Copyright@2009-2020 AII Right Reserve*/
@Slf4j
public class UserBizTest extends BaseJunitTest {@Autowiredprivate UserBiz userBiz;@Autowiredprivate RedisTemplate<String,String> redisTemplate;@Testpublic void getCircleUser() {// 初始化数据Map<Double, Double> locMap = new HashMap<>(); // <纬度(x),经度(y)>locMap.put(121.576334, 31.168569);locMap.put(121.587664, 31.205503);locMap.put(121.60586, 31.221726);locMap.put(121.65238, 31.199703);locMap.put(121.544749, 31.204989);locMap.put(121.506297, 31.03268);Map<Double, String> cityMap = new HashMap<>();cityMap.put(121.576334, "上海希奥信息科技有限公司");cityMap.put(121.587664, "上海火车站");cityMap.put(121.60586, "上海人民广场");cityMap.put(121.65238, "上海中医药大学");cityMap.put(121.544749, "上海漕河泾经开区新创业园");cityMap.put(121.506297, "上海竹林工业园");System.out.println("--------------------------------- start to redis sync save Coordinate ---------------------------------");// 定义坐标信息for (Map.Entry<Double, Double> entry : locMap.entrySet()) {Point point = new Point(entry.getKey(), entry.getValue());redisTemplate.opsForGeo().add("user-local", point, cityMap.get(entry.getKey()));}// 设置检索范围Point point = new Point(121.587623,31.201719);Circle circle = new Circle(point, new Distance(5, Metrics.KILOMETERS));// 定义返回结果参数,如果不指定默认只返回content即保存的member信息RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(5);GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius("user-local", circle,args);List<GeoResult<RedisGeoCommands.GeoLocation<String>>> list = results.getContent();for (GeoResult<RedisGeoCommands.GeoLocation<String>> l1 : list) {System.out.println("name : " + l1.getContent().getName() +"  distance : " + l1.getDistance() +" point :" + l1.getContent().getPoint());//}System.out.println("--------------------------------- end to sync save Coordinate ---------------------------------");}}

源码解析

1、坐标添加 add

注:支持单点、多点集合Map同时添加

  • point:元素属性x(经度),y(纬度)
/** (non-Javadoc)* @see org.springframework.data.redis.core.GeoOperations#add(java.lang.Object, org.springframework.data.geo.Point, java.lang.Object)*/@Overridepublic Long add(K key, Point point, M member) {byte[] rawKey = rawKey(key);byte[] rawMember = rawValue(member);return execute(connection -> connection.geoAdd(rawKey, point, rawMember), true);}/** (non-Javadoc)* @see org.springframework.data.redis.core.GeoOperations#add(java.lang.Object, org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation)*/@Overridepublic Long add(K key, GeoLocation<M> location) {return add(key, location.getPoint(), location.getName());}/** (non-Javadoc)* @see org.springframework.data.redis.core.GeoOperations#add(java.lang.Object, java.util.Map)*/@Overridepublic Long add(K key, Map<M, Point> memberCoordinateMap) {byte[] rawKey = rawKey(key);Map<byte[], Point> rawMemberCoordinateMap = new HashMap<>();for (M member : memberCoordinateMap.keySet()) {byte[] rawMember = rawValue(member);rawMemberCoordinateMap.put(rawMember, memberCoordinateMap.get(member));}return execute(connection -> connection.geoAdd(rawKey, rawMemberCoordinateMap), true);}/** (non-Javadoc)* @see org.springframework.data.redis.core.GeoOperations#add(java.lang.Object, java.lang.Iterable)*/@Overridepublic Long add(K key, Iterable<GeoLocation<M>> locations) {Map<M, Point> memberCoordinateMap = new LinkedHashMap<>();for (GeoLocation<M> location : locations) {memberCoordinateMap.put(location.getName(), location.getPoint());}return add(key, memberCoordinateMap);}

2、删除坐标remove

注:根据元素名称进行删除,支持多个同时删除

 /*** Remove the {@literal member}s.** @param key must not be {@literal null}.* @param members must not be {@literal null}.* @return Number of elements removed. {@literal null} when used in pipeline / transaction.* @since 2.0*/@NullableLong remove(K key, M... members);

3、查询周边radius

注:支持多种条件检索周边

Circle对象属性:

  • Point:需要检索的中心点坐标;
  • Distance:value为检索半径范围;Metric枚举类型为检索范围单位
KILOMETERS(6378.137, "km"), MILES(3963.191, "mi"), NEUTRAL(1, "");

GeoRadiusCommandArgs对象方法:

注:作用指定返回数据结果参数

  • includeCoordinates:返回结果包含坐标信息

  • includeDistance:返回结果包含具中心坐标距离信息

  • sortAscending:按照距离升序排序

  • sortDescending:按照距离降序排序

  • limit:返回结果数量限制

/*** Create new {@link GeoRadiusCommandArgs}.** @return never {@literal null}.*/public static GeoRadiusCommandArgs newGeoRadiusArgs() {return new GeoRadiusCommandArgs();}/*** Sets the {@link Flag#WITHCOORD} flag to also return the longitude, latitude coordinates of the matching items.** @return*/public GeoRadiusCommandArgs includeCoordinates() {flags.add(Flag.WITHCOORD);return this;}/*** Sets the {@link Flag#WITHDIST} flag to also return the distance of the returned items from the specified center.** @return never {@literal null}.*/public GeoRadiusCommandArgs includeDistance() {flags.add(Flag.WITHDIST);return this;}/*** Sort returned items from the nearest to the furthest, relative to the center.** @return never {@literal null}.*/public GeoRadiusCommandArgs sortAscending() {sortDirection = Direction.ASC;return this;}/*** Sort returned items from the furthest to the nearest, relative to the center.** @return never {@literal null}.*/public GeoRadiusCommandArgs sortDescending() {sortDirection = Direction.DESC;return this;}/*** Limit the results to the first N matching items.** @param count* @return never {@literal null}.*/public GeoRadiusCommandArgs limit(long count) {Assert.isTrue(count > 0, "Count has to positive value.");limit = count;return this;}

radius源码解析:

/*** Get the {@literal member}s within the boundaries of a given {@link Circle}.** @param key must not be {@literal null}.* @param within must not be {@literal null}.* @return never {@literal null} unless used in pipeline / transaction.* @since 2.0* @see <a href="https://redis.io/commands/georadius">Redis Documentation: GEORADIUS</a>*/@NullableGeoResults<GeoLocation<M>> radius(K key, Circle within);/*** Get the {@literal member}s within the boundaries of a given {@link Circle} applying {@link GeoRadiusCommandArgs}.** @param key must not be {@literal null}.* @param within must not be {@literal null}.* @param args must not be {@literal null}.* @return never {@literal null} unless used in pipeline / transaction.* @since 2.0* @see <a href="https://redis.io/commands/georadius">Redis Documentation: GEORADIUS</a>*/@NullableGeoResults<GeoLocation<M>> radius(K key, Circle within, GeoRadiusCommandArgs args);/*** Get the {@literal member}s within the circle defined by the {@literal members} coordinates and given* {@literal radius}.** @param key must not be {@literal null}.* @param member must not be {@literal null}.* @param radius* @return never {@literal null} unless used in pipeline / transaction.* @since 2.0* @see <a href="https://redis.io/commands/georadiusbymember">Redis Documentation: GEORADIUSBYMEMBER</a>*/@NullableGeoResults<GeoLocation<M>> radius(K key, M member, double radius);/*** Get the {@literal member}s within the circle defined by the {@literal members} coordinates and given* {@literal radius} applying {@link Metric}.** @param key must not be {@literal null}.* @param member must not be {@literal null}.* @param distance must not be {@literal null}.* @return never {@literal null} unless used in pipeline / transaction.* @since 2.0* @see <a href="https://redis.io/commands/georadiusbymember">Redis Documentation: GEORADIUSBYMEMBER</a>*/@NullableGeoResults<GeoLocation<M>> radius(K key, M member, Distance distance);/*** Get the {@literal member}s within the circle defined by the {@literal members} coordinates and given* {@literal radius} applying {@link Metric} and {@link GeoRadiusCommandArgs}.** @param key must not be {@literal null}.* @param member must not be {@literal null}.* @param distance must not be {@literal null}.* @param args must not be {@literal null}.* @return never {@literal null} unless used in pipeline / transaction.* @since 2.0* @see <a href="https://redis.io/commands/georadiusbymember">Redis Documentation: GEORADIUSBYMEMBER</a>*/@NullableGeoResults<GeoLocation<M>> radius(K key, M member, Distance distance, GeoRadiusCommandArgs args);

异常现象

Caused by: io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'GEOADD'


org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'GEOADD'at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:54)at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:52)at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:41)at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)at org.springframework.data.redis.connection.lettuce.LettuceConnection.convertLettuceAccessException(LettuceConnection.java:273)at org.springframework.data.redis.connection.lettuce.LettuceGeoCommands.convertLettuceAccessException(LettuceGeoCommands.java:424)at org.springframework.data.redis.connection.lettuce.LettuceGeoCommands.geoAdd(LettuceGeoCommands.java:78)at org.springframework.data.redis.connection.DefaultedRedisConnection.geoAdd(DefaultedRedisConnection.java:1187)at org.springframework.data.redis.connection.DefaultStringRedisConnection.geoAdd(DefaultStringRedisConnection.java:2908)at org.springframework.data.redis.core.DefaultGeoOperations.lambda$add$0(DefaultGeoOperations.java:60)at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:228)at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188)at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96)at org.springframework.data.redis.core.DefaultGeoOperations.add(DefaultGeoOperations.java:60)at com.gmall.user.server.UserBizTest.getCircleUser(UserBizTest.java:52)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)at org.junit.runners.ParentRunner.run(ParentRunner.java:413)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'GEOADD'at io.lettuce.core.ExceptionFactory.createExecutionException(ExceptionFactory.java:135)at io.lettuce.core.ExceptionFactory.createExecutionException(ExceptionFactory.java:108)at io.lettuce.core.protocol.AsyncCommand.completeResult(AsyncCommand.java:120)at io.lettuce.core.protocol.AsyncCommand.complete(AsyncCommand.java:111)at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:654)at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:614)at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:565)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)at java.lang.Thread.run(Thread.java:748)

解决方案:

更换redis版本,因为redis GEO是从>=3.2版本之后开始支持

最后

源码地址:https://gitee.com/mackjie/gmall-service

项目中gmall-batch -->test-->com.gmall.user.server.UserBizTest#getCircleUser()

这个技能 今天你学到了吗?^_^

SpringBoot redis GEO 实战应用相关推荐

  1. springboot redis 刷新时间_「SpringBoot实战」SpringCache + Redis实现数据缓存

    关注我的微信公众号:后端技术漫谈 不定期推送关于后端开发.爬虫.算法题.数据结构方面的原创技术文章,以及生活中的逸闻趣事. 我目前是一名后端开发工程师.主要关注后端开发,数据安全,网络爬虫,物联网,边 ...

  2. 基于Redis GEO(地理位置) 实现附近的人,商家等相关功能实现 使用SpringBoot Redis工具类

    Redis GEO 1.基本介绍 1.Redis GEO 2.基础语法 GEOADD GEOPOS GEODIST GEORADIUS GEOHASH 2.可用于实现的功能 3.SpringBoot实 ...

  3. SpringBoot 使用 Redis Geo 实现查找附近的位置-附近的人功能

    SpringBoot 使用 Redis Geo 实现查找附近的位置 6个操作命令 Redis 命令 描述 GEOADD 增加某个地理位置的坐标 GEOPOS 获取某个地理位置的坐标 GEODIST 获 ...

  4. Redis数据实战之GEO在LBS中应用与自定义新数据类型

    Redis数据实战之GEO在LBS中应用与自定义新数据类型 引言 面向 LBS 应用的 GEO 数据类型 GEO 的底层结构 GeoHash 的编码方法 如何操作 GEO 类型 如何自定义数据类型 R ...

  5. redis 判断存在性_实战 | springboot+redis+拦截器 实现接口幂等性校验

    来源:https://www.jianshu.com/p/6189275403ed 一.概念 幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如: 订单接口, 不能 ...

  6. Redis实战 - 11 Redis GEO 实现附近的人功能

    各种社交软件里面都有附件的人的需求,在该应用中,我们查询附近1公里的食客,同时只需查询出20个即可. 文章目录 1. Redis GEO常用命令 2. 上传用户地理位置 1. RedisKeyCons ...

  7. SpringBoot+Redis+Cookies实现高并发的购物车

    案例实战:SpringBoot+Redis+Cookies实现高并发的购物车 步骤1:代码逻辑 /*** 添加购物车*/@PostMapping(value = "/addCart" ...

  8. springboot做网站_Github点赞接近100k的SpringBoot学习教程+实战推荐!牛批!

    如果觉得看完文章对你有帮助记得点个赞,不要做收藏党.丢进收藏夹吃灰哦! 很明显的一个现象,除了一些老项目,现在 Java 后端项目基本都是基于 Spring Boot 进行开发,毕竟它这么好用以及天然 ...

  9. 腾讯云短信服务实现 Java 发送手机验证码(SpringBoot+Redis 实现)

    文章目录 腾讯云短信服务实现 Java 发送手机验证码(SpringBoot+Redis 实现) 1.打开腾讯云短信服务 2.创建短信签名 3.创建短信正文模板 4.等待全部审核完毕即可 5.发送短信 ...

最新文章

  1. 摸不到视频里的犀牛,却能在它身上画画,特效紧贴凹凸表面,动也不掉:全靠免费AE插件...
  2. npm学习(二)之如何防止权限错误
  3. Google C++单元测试框架(Gtest)系列教程之六——FAQ节选
  4. STM32的PA15、PB3、 PB4管脚作普通管脚的解决办法
  5. mac安装win7之后鼠标失灵_排雷之后终于找到了解决mac安装Homebrew的报错
  6. 要求员工自愿无偿加班 特斯拉真是拼...
  7. TensorFlow 2.0要来了,tf.contrib要砍了 | 有什么意见你说啊
  8. 数据分析,如何做才算“深入”?
  9. hive get_json_object json_tuple json解析详解
  10. 菜鸟程序猿的工作心态
  11. 最大流最小割算法证明
  12. STVD cpstm8 miss } in struct/union definition
  13. IT 必备电脑快捷键
  14. XP安装SQL2000个人版
  15. 【Excel2019(十二):Match与Index函数】【函数语法+与VLOOKUP比较+单元格引用原理+认识COLUMN函数+使用Match与VLOOKUP函数嵌套返回多列结果】
  16. html标签-meta
  17. python学习笔记-修改pip下载源-创建虚拟环境
  18. 更完美 联想乐Phone获取root权限教程
  19. Gym - 102263 B - Road to Arabella
  20. 连小白都能看懂的微信开发之测试账号申请

热门文章

  1. MATLAB上用十一行代码实现深度学习…
  2. 基于强化学习与深度强化学习的游戏AI训练
  3. 2008R2虚拟机重启后进入系统恢复界面
  4. Leetcode -- Verify Preorder Serialization of a Binary Tree
  5. 嵌入式Linux(十三)RTC实时时钟
  6. 软件测试实习生(月薪3k-5k)需要具备哪些技能才能找到工作?
  7. Dojo 1.6 官方教程:Dojo中的事件
  8. python列表转集合_Pandas把dataframe或series转换成list的方法
  9. Mikrotik路由器(routerOS)调试环境搭建
  10. 如何计算IT投资回报(ROI)