如何在项目当中使用redis进行范围搜索

目录

 

如何将地理位置数据保存到 Redis 中以支持范围查询

Redis 中的 GEO 类型是什么?

如何保存 GEO 数据到 Redis 

分段解释: 

RedisKey.POSTS_ANIMALS_LOCATIONS

new Point(longitude, latitude)

 

如何进行范围搜索

Redis GEO 范围搜索核心语句

1.redisTemplate.opsForGeo().search(...)

2. RedisKey.POSTS_ANIMALS_LOCATIONS

3. GeoReference.fromCoordinate(x, y)

4. new Distance(5000)

5. RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs()

6. .includeDistance()

搜索结果判空

提取 Redis 搜索结果 


 

如何将地理位置数据保存到 Redis 中以支持范围查询

Redis 中的 GEO 类型是什么?

Redis 提供了 GEO 命令支持地理位置信息的存储和查询,底层使用 Geohash 编码 + Sorted Set(有序集合) 实现。你可以对其进行:

  • 添加坐标(经纬度);

  • 查询指定位置一定范围内的成员;

  • 获取两个成员之间的距离;

  • 查询某个成员的位置等。

如何保存 GEO 数据到 Redis 

redisTemplate.opsForGeo().add(RedisKey.POSTS_ANIMALS_LOCATIONS, // Redis 中的 key,用来存所有帖子的位置new Point(animalsRescueDTO.getLongitude(), animalsRescueDTO.getLatitude()), // 经纬度(Point 构造顺序:经度, 纬度)posts.getPostId().toString() // 这个帖子的位置用帖子 ID 作为唯一标识(member)
);

 

👇 实际等价于 Redis 命令: 

GEOADD POSTS_ANIMALS_LOCATIONS 113.1234 23.5678 "123"
  • POSTS_ANIMALS_LOCATIONS 是存储地理数据的 Redis 键

  • 113.1234 是经度(longitude)

  • 23.5678 是纬度(latitude)

  • "123" 是帖子 ID(即你 posts.getPostId()

分段解释: 

redisTemplate.opsForGeo()

这是 Spring Data Redis 提供的模板方法,用于执行 GEO 类型操作 的入口。

它返回的是一个 GeoOperations<K, V> 对象,可以执行下面这些操作:

方法功能
add(...)添加地理位置点(经度、纬度 + 名称)
search(...)按照范围搜索附近的点
distance(...)计算两个点之间的距离
position(...)获取某个 member 的坐标
hash(...)获取某个 member 的 geohash 值

RedisKey.POSTS_ANIMALS_LOCATIONS

这是一个 Redis 的 Key,表示你所有帖子位置都保存在这个 key 下的 GEO 类型中。

 

new Point(longitude, latitude)

这是一个 Spring 提供的 org.springframework.data.geo.Point 类型,用于封装经纬度。

⚠️ 注意顺序:

Point(x, y) 中,x 是经度y 是纬度

 

Redis 是使用底层的 ZSet + Geohash 来实现这个数据结构的:

  • 每个点会被编码成 geohash,对应 ZSet 的 score

  • 可以用 ZRANGEGEORADIUS 等方式高效查询范围

 

如何进行范围搜索

Redis GEO 范围搜索核心语句

GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().search(RedisKey.POSTS_ANIMALS_LOCATIONS, // Redis 中 GEO 数据所在的 keyGeoReference.fromCoordinate(x, y), // 查询圆心:经度 x,纬度 ynew Distance(5000),                // 查询半径:5000 米(5 公里)RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance()             // 查询结果中返回每个点的距离
);
参数类型说明
keyStringRedis 中存储 GEO 数据的 key,也就是你存储地理数据时使用的那个 key。例如你之前可能使用 RedisKey.POSTS_ANIMALS_LOCATIONS 存储了所有帖子的地理位置信息。
geoReferenceGeoReference查询圆心坐标(经纬度)。这代表你要查询的中心点的位置。
distanceDistance查询的范围半径,单位是米(m),表示你想要查询中心点 geoReference 周围多少米以内的所有地理位置。
argsGeoSearchCommandArgs查询参数的设置,可以设置排序、返回距离等额外选项。

 

1.redisTemplate.opsForGeo().search(...)

  • opsForGeo():Spring Data Redis 提供的 GEO 操作 API

  • search(...):封装了 Redis 6.2+ 的 GEOSEARCH 命令,是范围查找的入口

2. RedisKey.POSTS_ANIMALS_LOCATIONS

  • 这是 Redis 中用于保存 GEO 数据的键名(key)

  • 对应 Redis 的底层命令示例:

 

3. GeoReference.fromCoordinate(x, y)

这是查询的中心点:

GeoReference.fromCoordinate(double longitude, double latitude)

注意顺序是:

经度在前(x)纬度在后(y)

这个代表:

“我现在的位置是 (经度, 纬度),请查我附近的 member”

你传入的 (x, y) 一般来源于用户定位(如小程序的 wx.getLocation()

 

4. new Distance(5000)

  • Distance 是 Spring 提供的距离对象

  • 默认单位是 米(Meters)

  • 所以这是一个 以中心点为圆心、半径为 5000 米(5 公里) 的范围查找

 

5. RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs()

这是搜索的“附加参数”,你可以在里面设置返回什么信息、是否排序、返回几个等。

是一个“无参的静态方法”,作用是:

返回一个新的 GeoSearchCommandArgs 对象,用来配置 Redis GEO 查询参数。

你得到了一个 GeoSearchCommandArgs 类型的对象,后面可以继续链式调用:

举例:

RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs()
.includeDistance().limit(5).sortAscending();

 

6. .includeDistance()

这个非常重要!

  • 它的作用是:让返回结果中附带每个点距离圆心的“实际距离”

  • 否则默认只返回哪些 member 在范围内,不告诉你它们距离多远

搜索结果判空

if (results == null || results.getContent().isEmpty()) {return nearbyRescues;  // 无结果,直接返回空列表
}

 

提取 Redis 搜索结果 

Map<Integer, Distance> distanceMap = new HashMap<>();
List<Integer> ids = new ArrayList<>();for (GeoResult<RedisGeoCommands.GeoLocation<String>> location : results.getContent()) {Integer postId = Integer.valueOf(location.getContent().getName());Distance distance = location.getDistance();ids.add(postId);distanceMap.put(postId, distance);
}

 

 

👉 这里构建:

  • ids:用于批量查数据库

  • distanceMap:用于后续给每个 PostsVo 设置距离属性

GeoResults
└── getContent() → List<GeoResult>└── GeoResult├── getContent() → GeoLocation│    ├── getName() → 帖子ID("123")│    └── getPoint() → 经纬度└── getDistance() → 到查询中心的距离

🔹 每个 GeoResult 里包含:

  • .getName() → Redis GEO 中的 member(这里是帖子 ID),实际就是 Redis GEO 中的 member

  • .getDistance() → 距离圆心的距离

GeoResults<GeoLocation<String>> results = {List<GeoResult<GeoLocation<String>>> content = [GeoResult {content: GeoLocation {name: "123",                    // member → 帖子IDpoint: Point(113.2345, 23.4567) // 坐标},distance: Distance(4213.5)         // 到查询点的距离(单位米)},GeoResult {content: GeoLocation {name: "124",point: Point(...)},distance: ...},...]
}

完整范围搜索的例子

@Override@Transactionalpublic ArrayList<PostsVo> getNearbyRescue(double y, double x) {GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().search(RedisKey.POSTS_ANIMALS_LOCATIONS,                                       // Redis 中存储地理位置数据的键GeoReference.fromCoordinate(x, y),        // 查询的圆心坐标 (经度, 纬度)new Distance(5000),                       // 查询的半径范围为 5000 米(5 公里)RedisGeoCommands.GeoSearchCommandArgs     // 额外的查询参数.newGeoSearchArgs().includeDistance()                    // 返回结果中包含距离);//一系列的封装返回前端的操作ArrayList<PostsVo> nearbyRescues = new ArrayList<>();// 检查查询是否有结果if (results == null || results.getContent().isEmpty()) {return nearbyRescues;  // 没有找到附近的帖子,返回空列表}// 用于存储 postId 和其对应的 DistanceMap<Integer, Distance> distanceMap = new HashMap<>();List<Integer> ids = new ArrayList<>();// 遍历 Geo 结果,提取 postId 和 distancefor (GeoResult<RedisGeoCommands.GeoLocation<String>> location : results.getContent()) {Integer postId = Integer.valueOf(location.getContent().getName());Distance distance = location.getDistance();ids.add(postId);distanceMap.put(postId, distance);}// 批量查询 postsList<Posts> postsList = postsMapper.selectBatchIds(ids);// 转换为 PostsVo 并将距离赋值进去nearbyRescues = postsList.stream().map(post -> {PostsVo postsVo = BeanUtil.copyProperties(post, PostsVo.class);// 假设 posts 对象中有 getPostId() 方法获取 idDistance d = distanceMap.get(post.getPostId());if(d != null){// 将距离单位转换为公里(如果需要),这里假设 d.getValue() 返回的是米postsVo.setDistance(d.getValue() / 1000.0);}// 根据animalId查询动物信息Animals animals = animalsMapper.selectById(post.getAnimalId());AnimalsVo animalsVo = BeanUtil.copyProperties(animals, AnimalsVo.class);String[] photos = animals.getPhotos().split(",");animalsVo.setPhotos(photos);postsVo.setAnimalsVo(animalsVo);return postsVo;}).collect(Collectors.toCollection(ArrayList::new));return nearbyRescues;}

Redis GEO 本质上是在 Redis 中保存地理位置数据(使用经纬度 + key + member 的形式),然后通过 GEORADIUS / GEOSEARCH 实现地理范围搜索。

 

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

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

相关文章

物联网低功耗保活协同优化方案:软硬件与WiFi网关动态联动

目录 一、总体方案概述 二、架构组成 2.1 系统拓扑 2.2 硬件端(MCU + WiFi 模组) 2.3 WiFi 网关 2.4 云端服务器 三、低功耗保活技术设计模式 3.1 模式一:定时唤醒 + MQTT 保活 3.1.1 设备端 3.1.2 优势 3.2 模式二:网关保活代理 + 本地网络唤醒 3.2.1 网关功能…

UniApp+Vue3微信小程序二维码生成、转图片、截图保存整页

二维码生成工具使用uqrcode/js&#xff0c;版本4.0.7 官网地址&#xff1a;uQRCode 中文文档&#xff08;不建议看可能会被误导&#xff09; 本项目采用了npm引入方式&#xff0c;也可通过插件市场引入&#xff0c;使用上会略有不同 准备工作&#xff1a; 安装&#xff1a;pnpm…

Zenmap代理情况下无法扫描ip

原因是开了代理会报错 error “only ethernet devices can be used for raw scans on Windows” 在扫描参数后加 -sT -Pn&#xff0c;但会导致结果太多 例如&#xff1a;nmap -sT -T4 -A -v -Pn 10.44.2.0/24 如果你只是想找没人用的IP&#xff0c;你不需要搞复杂的原始层扫描&…

将多个值关联到同一个 key的map(key可以重复的map)示例

在 Java 中&#xff0c;标准的 Map 接口要求 key 必须唯一&#xff0c;如果需要 key 可重复 且保持 插入顺序 的数据结构&#xff0c;可以使用以下方案&#xff1a; 1. 使用 List<Map.Entry<K, V>> 最直接的方式是用链表存储键值对&#xff0c;允许重复 key&…

Arthas(阿尔萨斯)

一、Arthas 是什么&#xff1f; Arthas&#xff08;阿尔萨斯&#xff09;是阿里巴巴开源的一款 Java 在线诊断工具&#xff0c;基于 Java Agent 和字节码增强技术实现。它无需重启 JVM&#xff0c;即可动态追踪代码执行、实时查看 JVM 状态、修改代码逻辑&#xff0c;是生产环…

深入解读Qwen3技术报告(三):深入剖析Qwen3模型架构

重磅推荐专栏&#xff1a; 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域&#xff0c;包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用&#xff0c;以及与之相关的人工智能生成内容&#xff…

UE4游戏查找本地角色数据的方法-SDK

UE4中&#xff0c;玩家的表示通常涉及以下几个类&#xff1a; APlayerController: 代表玩家的控制逻辑&#xff0c;处理输入等。 APawn: 代表玩家在世界中的实体&#xff08;比如一个角色、一辆车&#xff09;。APlayerController 控制一个 APawn。 ACharacter: APawn 的一个…

springboot+vue实现服装商城系统(带用户协同过滤个性化推荐算法)

今天教大家如何设计一个服装商城 , 基于目前主流的技术&#xff1a;前端vue3&#xff0c;后端springboot。 同时还带来的项目的部署教程。 系统最大的亮点是使用了两个推荐算法: 1. 基于Jaccard算法的用户浏览历史推荐。 2. 基于用户的协同过滤算法个性化推荐。 还有核心的商…

ERROR: Could not install packages due to an OSError: [WinError 5] 拒绝访问

有可能是设置了代理 unset ALLPROXY 或者注释掉 当然也有可能是其他原因 权限不足​​ 以管理员身份运行 CMD/PowerShell&#xff0c;或使用 --user 安装 ​​文件被占用​​ 关闭杀毒软件或重启电脑 Python 环境损坏​​ 重新安装 Python 或使用虚拟环境 ​​ 杀毒软件阻止…

【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】

在智能家电与健康器械市场爆发的今天&#xff0c;核心驱动技术正成为产品突围的关键。传统电机控制方案面临集成度低、开发周期长、性能瓶颈三大痛点&#xff0c;而爱普特电子带来的APT32F1023H8S6单片机无感三合一方案&#xff0c;正在掀起一场智能电机控制的技术革命。 爆款基…

一个.NET开源、轻量级的运行耗时统计库

前言 在.NET开发中&#xff0c;为了准确统计对应方法的执行时间&#xff0c;我们最常用的方式是手动使用 Stopwatch 来显式编写计时逻辑&#xff0c;但是假如你需要大量的使用 Stopwatch 来进行耗时统计的话不利于保持代码的整洁和增加代码的维护成本。 项目介绍 MethodTime…

嵌入式鸿蒙openharmony应用开发环境搭建与工程创建实现

各位小伙伴大家好,本周开始分享鸿蒙开发相关的内容,从基础的配置方法到各种功能的实现,探索国产操作系统的奥秘。 第一:观察结果 第二:开源语言 ArkTS是鸿蒙应用开发中使用的TypeScript超集,提供了一套丰富的API来构建应用界面和逻辑。 第三:环境搭建 步骤 1 通过如…

软考 组合设计模式

组合设计模式&#xff08;Composite Pattern&#xff09;是结构型设计模式之一&#xff0c;它的核心思想是将对象组合成树形结构来表示“部分-整体”的层次结构&#xff0c;使得用户对单个对象和组合对象的使用具有一致性。 主要概念&#xff1a; 组件&#xff08;Component&a…

vue 中的v-once

&#x1f530; 基础理解 ✅ 语法&#xff1a; <span v-once>{{ msg }}</span>✅ 效果&#xff1a; • 只渲染一次&#xff0c;之后无论数据如何变化&#xff0c;该内容都不会更新。 • 非常适用于静态内容或首次加载后不需要变化的数据。&#x1f9ea; 示例&…

GPU训练和call方法

知识点回归: CPU性能的查看:看架构代际、核心数、线程数GPU性能的查看:看显存、看级别、看架构代际GPU训练的方法:数据和模型移动到GPU device上类的call方法:为什么定义前向传播时可以直接写作self.fc1(x)import torch import torch.nn as nn import torch.optim as opti…

人脸识别备案开启安全防护模式!紧跟《办法》!

国家互联网信息办公室与公安部于 2025 年 3 月 13 日联合公布了《人脸识别技术应用安全管理办法》&#xff08;以下简称《办法》&#xff09;&#xff0c;并自 2025 年 6 月 1 日起正式施行。其中&#xff0c;人脸识别备案成为了规范技术应用、守护信息安全的关键一环。​ 一、…

LeetCode:贪心算法

目录 一、分发饼干 二、摆动序列 三、最大子数组和 四、买卖股票的最佳时机II 五、跳跃游戏 六、跳跃游戏II 七、K次取反后最大化的数组和 八、加油站 九、分发糖果 十、柠檬水找零 十一、根据身高重建队列 一、分发饼干 455. 分发饼干 - 力扣&#xff08;LeetCode…

企业级 Hosts 自动化管理实战:基于 HTTP 检测的高可用域名解析方案

摘要 本文针对企业级域名解析稳定性需求&#xff0c;提供一套从IP 检测到Hosts 更新的完整自动化解决方案。通过 HTTP 状态码检测、权威 DNS 解析、原子化文件操作等核心技术&#xff0c;结合多行业真实案例&#xff0c;详细阐述方案设计、脚本实现与生产部署&#xff0c;帮助…

基于springboot+vue网页系统的社区义工服务互动平台(源码+论文+讲解+部署+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统背景 在社会文明程度不断提升、社区治理需求持续深化的大背景下&#xff0c;社区义工服务作为…

从细胞工厂到智能制造:Extracellular 用时序数据库 TDengine 打通数据生命线

作为一家位于英国的前沿生物科技公司&#xff0c;Extracellular 专注于细胞培养产品的规模化制造&#xff0c;致力于通过优化生物工艺流程&#xff0c;加速细胞类产品从实验室走向大规模生产的落地。为了实现这一目标&#xff0c;他们需要一个稳定、高效、可扩展的数据平台&…