Redis那些事儿(三)

文章目录

    • 1. 前言
    • 2. 常用api介绍
    • 3. 需求假设(获取离我最近的停车场)
    • 4. 代码示例

1. 前言

        接着上一篇Redis那些事儿(二) ,这一篇主要介绍Redis基于Geo数据结构实现的地理服务,它提供了一种方便的方式来存储和处理与地理位置相关的数据。Geo数据结构是Redis的一种特殊数据类型,用于存储地理位置信息,每个地理位置被表示为经度和纬度的坐标,可以将这些坐标与一个或多个成员关联起来。Redis的地理服务提供了一套简单而强大的功能,可以方便地存储和处理与地理位置相关的数据,它适用于许多应用场景,如地理定位、附近的人、附近的店铺搜索、附近的停车场、附近的地铁站…等等,大大提升了定位排序的效率。

2. 常用api介绍

        Redis地理服务API方法包括:GEOADD(向Geo数据结构中添加一个或多个地理位置信息);GEODIST(计算两个地理位置之间的距离);GEORADIUS(获取给定地理位置附近一定范围内的成员);GEOPOS(获取给定成员的经纬度坐标);GEOHASH(获取给定成员的Geohash值)…以上都是Geo地理服务内置的常用方法,接下来还是基于开发中的StringRedisTemplate对象作为切入点,更直观地说明实际应用中对于Geo地理服务地应用。
        StringRedisTemplate中定义了RedisGeoCommands的接口,RedisGeoCommands中封装了一系列的内置方法及子类,所以Redis中基于opsForGeo()的操作都离不开RedisGeoCommands,如下为部分截图:
RedisGeoCommands部分截图

Geo数据结构中存入坐标数据,redisTemplate.opsForGeo().add(key, locations)

		List<Park> parks = getParks(); //TODO 获取停车场列表信息//初始化Redis区域对象集合List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>();for (Park park : parks) {//实例化ponit对象,传参[经度、纬度]Point point = new Point(park.getLng(), park.getLat());//构造location对象,传参[name值(一般取ID)、point对象]RedisGeoCommands.GeoLocation<String> location = new RedisGeoCommands.GeoLocation<>(park.getParkId() + "", point);locations.add(location);}String key = "GEO_PARK_KEY";//存入坐标数据redisTemplate.opsForGeo().add(key, locations);

Geo数据结构中删除坐标数据,redisTemplate.opsForGeo().remove(key, …members)

		String key = "GEO_PARK_KEY";//删除单个坐标数据(parkId为单个停车场ID,类型为String)redisTemplate.opsForGeo().remove(key, parkId);//删除多个坐标数据(第一个参数为key,后面可以传入多个parkId)redisTemplate.opsForGeo().remove(key, parkId1, parkId2, parkId3);

Geo数据结构中检索坐标数据由近到远,redisTemplate.opsForGeo().radius(key, within, args)

		String key = "GEO_PARK_KEY";//检索20公里内的Distance distance = new Distance(20, Metrics.KILOMETERS);//以目标坐标为圆心,distance为半径的圆圈范围,其中lng代表中心坐标的经度、lat代表中心坐标的纬度Circle within = new Circle(new Point(lng, lat), distance);//条件参数,按照距离查询,默认就是升序RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance();//执行查询GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius(key, within, args);

Geo数据结构中检索坐标数据由近到远,redisTemplate.opsForGeo().search(key, reference, distance, args)

		String key = "GEO_PARK_KEY";//检索20公里内的Distance distance = new Distance(20, Metrics.KILOMETERS);//条件参数,按照距离查询,默认就是升序RedisGeoCommands.GeoSearchCommandArgs args = RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance();//中心点位确认,其中lng代表中心坐标的经度、lat代表中心坐标的纬度GeoReference<String> reference = GeoReference.fromCoordinate(lng, lat);//执行查询GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().search(key, reference, distance, args);

        以上列了四个最常用的方式,类似于我们最常规的CURD,其中最后两个radius和search是查询方法,二者最终查询的结果是一致的,只是手段方式不同而已!

3. 需求假设(获取离我最近的停车场)

        这个时候有人就说了:我使用GeodeticCalculator工具类在代码中计算距离也很方便的啊。我想了想,确实很方便,只需要引入geodesy的依赖,就可以直接使用GeodeticCalculator的calculateGeodeticCurve方法就可以计算了,还不需要麻烦的用redis搞那么长的代码了。但是,问题来了,就以停车场为例,假如只有十几个停车场,遍历一下然后按升序排个序,很快就计算出了离我最近的停车场列表了。如果我有上千个或者上万个停车场,总不能遍历上万次然后再排序吧,那这速度就一言难尽了…如果这个时候使用redis的geo数据结构来读取,那就完美解决这个问题了。Redis提供的GeoHash算法功能对于这方面的需求就太好用了,那么,附近的停车场、附近的人、附近的商家就都是一个思路了!

4. 代码示例

	/*** 获取距离最近的停车场列表,由近到远* @param lng 当前位置经度* @param lat 当前位置纬度* @param page 页数(第n页)* @param size 每页数量(10、20...)* @param value 公里范围内(搜索范围半径)* @return*/public List<Park> getLatestParks(Double lng, Double lat, Integer page, Integer size, Double value){//计算分页起始参数Integer start = (page - 1) * size;Integer end = page * size;//查询redis,按照距离排序String key = "GEO_PARK_KEY";//检索value公里内的Distance distance = new Distance(value, Metrics.KILOMETERS);//以目标坐标为圆心,distance为半径的圆圈范围,其中lng代表中心坐标的经度、lat代表中心坐标的纬度Circle within = new Circle(new Point(lng, lat), distance);//条件参数,按照距离查询,默认就是升序,截止到endRedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(end);//执行查询GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius(key, within, args);if (results == null) {return new ArrayList<>();}//获取最终检索的内容List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = results.getContent();//截取从起始到结束,如果总数小于起始数就证明已经页数超了,返回空集合if (content.size() <= start) {return new ArrayList<>();}//初始化parkId集合List<Long> parkIds = new ArrayList<>();//初始化距离mapMap<String, Distance> distanceMap = new HashMap<>();//分页跳过之前的数据,并遍历赋值content.stream().skip(start).forEach(i->{String parkIdStr = i.getContent().getName();parkIds.add(Long.valueOf(parkIdStr));Distance dis = i.getDistance();distanceMap.put(parkIdStr, dis);});//固定排序String join = StringUtils.join(parkIds,",");//根据parkId集合获取park集合List<Park> newParks = parkService.list(new QueryWrapper<Park>().in("park_id", parkIds).last("ORDER BY FIELD(park_id," + join + ")")).stream().map(i -> {i.setDistance(distanceMap.get(i.getParkId() + "").getValue());return i;}).collect(Collectors.toList());return newParks;}

以上代码为由近到远获取距离最近的停车场列表的示例方法,仅供参考

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

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

相关文章

库房管理软件采购申请流程代码实现解析

300rmb掏了个javavue2的小系统&#xff0c;学习代码&#xff0c;调整下申请流程。 原有的入库流程是&#xff0c;库管&#xff08;admin&#xff09;提出采购申请给采购员&#xff08;caigou&#xff09;&#xff0c;采购员采购入库时点击入库完成采购入库流程。 想弄清后端代…

非关系型数据库Redis的安装【Linux】及常用命令

前言 Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的内存数据库管理系统&#xff0c;它以键值存储方式来存储数据&#xff0c;并且支持多种数据结构&#xff0c;如字符串、哈希、列表、集合、有序集合等。Redis最初由Salvatore Sanfilippo开发&#xff0c…

数据分析实战 | 关联规则分析——购物车分析

目录 一、数据及分析对象 二、目的及分析任务 三、方法及工具 四、数据读入 五、数据理解 六、数据预处理 七、生成频繁项集 八、计算关联度 九、可视化 一、数据及分析对象 数据集链接&#xff1a;Online Retail.xlsx 该数据集记录了2010年12月01日至2011年12月09日…

Docker 修改镜像的Digests值

最近工作中遇到个事情&#xff0c;我在本地虚拟机导出的镜像&#xff0c;导入到服务器发现镜像的digests是<none>&#xff0c;网上找了半天发现没有相关的解决方案&#xff0c;服务器上的源码是通过镜像的hash值拉取镜像没有Tag&#xff0c;镜像digests为<none>很痛…

21. 合并两个有序链表

Problem: 21. 合并两个有序链表 文章目录 思路1 递归实现2 迭代实现 Code 思路 方法1 递归实现 方法2 迭代实现 1 递归实现 分析问题 对于本题&#xff0c;合并两个有序链表A和B&#xff0c;mergeTwoLists&#xff08;A,B&#xff09;&#xff0c;递归只需要关注本层我要干什么…

性能优于BERT的FLAIR:一篇文章入门Flair模型

文章目录 What is FLAIR&#xff1f;FLAIR ModelContextual String Embedding for Sequence Labelingexample FLAIR Application AreaSentiment AnalysisNamed Entity RecognitionText Classification FLAIR一、什么是FLAIR&#xff1f;二、FLAIR Library的优势是什么&#xff…

23年面试总结

网易一面 231026 0、介绍下你自己 1、具体负责的工作内容 系统的建设与维护工作。环境搭建与维护、巡检、容量规划、CICD流水线管理、可观测指标建立、监控告警处理&#xff0c;用户的请求事件问题处 2、介绍一下http协议 http协议&#xff08;hyper text transfer protoco…

突破性技术!开源多模态模型—MiniGPT-5

多模态生成一直是OpenAI、微软、百度等科技巨头的重要研究领域&#xff0c;但如何实现连贯的文本和相关图像是一个棘手的难题。 为了突破技术瓶颈&#xff0c;加州大学圣克鲁斯分校研发了MiniGPT-5模型&#xff0c;并提出了全新技术概念“Generative Vokens "&#xff0c…

❤️ React的安装和使用(实战篇)

React的安装和使用 一、React的安装和使用 reactJs警告提示&#xff1a; This version of tar is no longer supported, and will not receive security updates. Please upgrade asap 翻译&#xff1a;tar2.2.2&#xff1a;此版本的tar不再受支持&#xff0c;将不会收到安全…

golang实现极简todolist

ToDoList 最近跟着qimi老师做了一个ToDoList&#xff0c;我做的GitHub地址贴在这里&#xff0c;但由于前端出了点问题&#xff0c;所以都是用postman进行测试 原项目地址 部分功能展示 删除代办 查找代办 下面给出思路 思路 其实这是一个很简单的增删改查的实现&#xff…

linux下使用vscode对C++项目进行编译

项目的目录结构 头文件swap.h 在自定义的头文件中写函数的声明。 // 函数的声明 void swap(int a,int b);swap.cpp 导入函数的声明&#xff0c;写函数的定义 #include "swap.h" // 双引号表示自定义的头文件 #include <iostream> using namespace std;// 函…

QR码应用实战:Spring Boot与ZXing完美结合

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 QR码应用实战&#xff1a;Spring Boot与ZXing完美结合 前言第一&#xff1a; 介绍QR码和ZXing第二&#xff1a;springboot整合zxing添加ZXing依赖生成二维码生成条形码 前言 …

LeetCode.6 N字形变换

一开始想的是真的创建一个数组 去按照题目所给的要求填入数据 最后输出不为空的数组项 但是不仅时间复杂度高 而且错误频繁出现 最终也没有提交成功 查阅题解后发现数组并不重要 假设我们忽略掉数组中的那些空白项 最终输出的结果就是numRows行的字符串的拼接 string conver…

HCIE-kubernetes(k8s)-Authentication身份验证

1、远程登录 1、kubeconfig方式 在master上都是以kubeconfig方式登录的&#xff0c;并不是说有一个文件叫kubeconfig。 默认使用的配置文件是~/.kube/config 这个配置文件&#xff0c;而这个配置文件是通过这个文件/etc/kubernetes/admin.conf 如果在node上执行命令&#xff…

apachesolr中简单使用

core使用 首先点击add core 可以看到报错solrconfig.xml不在new_core目录下&#xff0c;new_core是我们点击后自动创建的 那么我们将D:\solr2\solr-9.3.0\solr-9.3.0\server\solr\configsets下的任何一个目录下的conf拷贝到new_core过去 这里是使用_default下的conf目录拷贝…

【PC电脑windows环境下-[jetson-orin-NX]Linux环境下-下载工具esptool工具使用-相关细节-简单样例-实际操作】

【PC电脑windows环境下-[jetson-orin-NX]Linux环境下-下载工具esptool工具使用-相关细节-简单样例-实际操作】 1、概述2、实验环境3、 物品说明4-2、自我总结5、本次实验说明1、准备样例2、设置芯片3、编译4、下载5、验证 &#xff08;1&#xff09;windows环境下进行烧写1、下…

RabbitMQ 消息应答与发布

目录 一、消息应答 1、自动应答&#xff08;默认&#xff09; 2、手动消息应答的方法 ​编辑 3、消息重新入队 4、手动应答案列与效果演示 二、RabbitMQ持久化 1、队列持久化 2、消息持久化 三、不公平分发&#xff08;能者多劳&#xff0c;弱者少劳&#xff09; 1、…

C#中的GC

在C#&#xff08;C Sharp&#xff09;编程语言中&#xff0c;GC是指垃圾回收&#xff08;Garbage Collection&#xff09;的缩写。 垃圾回收是一种自动内存管理机制&#xff0c;在程序运行时负责自动分配和释放对象所占用的内存空间。它减轻了开发人员手动管理内存的负担&…

算法通过村第十八关-回溯|青铜笔记|什么叫回溯(中篇)

文章目录 前言回溯的核心问题撤销操作解释总结 前言 提示&#xff1a;阳光好的时候&#xff0c;会感觉还可以活很久&#xff0c;甚至可以活出喜悦。 --余秀华 回溯是非常重要的算法思想之一&#xff0c;主要解决一些暴力枚举也搞不定的问题&#xff08;这里埋个坑&#x1f4a3;…

NTFS文件系统解析(三)

1、引言 对于NTFS文件系统而言&#xff0c;无论文件内容本身&#xff0c;抑或真实的文件属性&#xff0c;都被称之为属性。 而正如前文说到的&#xff0c;NTFS预定义了16种属性用于文件系统的管理。 而通常情况下&#xff0c;往往只需要关注其中的某些属性即可。 2、属性头 …