redis_点评(25.附件店铺—把数据库里的店铺按【类型分组】,批量导入Redis 的 GEO 地理位置结构)

店铺数据批量导入 Redis GEO 详解

这段代码的核心目标是:把数据库里的店铺数据,按类型分组后,批量写入 Redis 的 GEO 结构,为后续"附近店铺"查询做准备。


一、整体流程概览


二、逐行代码拆解

1. 环境准备

java 复制代码
@Resource
private StringRedisTemplate stringRedisTemplate;

注入 StringRedisTemplate,用于操作 Redis,尤其是 GEO 相关命令。


2. 主方法 loadShopData()

java 复制代码
@Test
void loadShopData(){
    // 1. 查询店铺信息
    List<Shop> list = shopService.list();
  • 调用 shopService.list() 从数据库中查询所有店铺。

  • 得到 List<Shop>,包含所有店铺的ID、类型ID、经纬度等信息。


3. 按店铺类型分组

java 复制代码
// 2. 把店铺分组,按照typeId分组,typeId一致的放到一个集合
Map<Long, List<Shop>> map = list.stream()
    .collect(Collectors.groupingBy(Shop::getTypeId));
  • 使用 Java 8 Stream 的 Collectors.groupingBy,按 Shop::getTypeId(店铺类型ID)分组。

  • 结果:Map<Long, List<Shop>>,Key 是 typeId,Value 是该类型下的所有店铺列表。


4. 遍历分组,批量写入 Redis

java 复制代码
// 3. 分批完成写入Redis
for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
    // 3.1 获取类型id
    Long typeId = entry.getKey();
    String key = "shop:geo:" + typeId;

    // 3.2 获取同类型的店铺的集合
    List<Shop> value = entry.getValue();
    List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(value.size());

    // 3.3 构建GeoLocation对象
    for (Shop shop : value) {
        locations.add(new RedisGeoCommands.GeoLocation<>(
            shop.getId().toString(),      // member:店铺ID
            new Point(shop.getX(), shop.getY()) // 经纬度
        ));
    }

    // 3.4 批量写入Redis GEO
    stringRedisTemplate.opsForGeo().add(key, locations);
}
一、逐段关键解释
1. map.entrySet()
  • 所属:java.util.Map 接口的方法

  • 作用:把 Map 转成一个「键值对集合」,方便 for-each 遍历

  • 业务含义:遍历按 typeId 分组后的店铺数据,拿到每一组的 typeId 和该类型下的所有店铺


2. RedisGeoCommands.GeoLocation
  • 所属:Spring Data Redis 提供的地理位置实体类

  • 用途:专门给 Redis GEO 功能封装数据,只存两个东西:

    • name:成员名称(这里存店铺 ID,后续查询时可直接拿到)

    • point:坐标点(经度 + 纬度)


3. List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(shops.size());
  • 含义:创建一个 List 集合,名字叫 locations,只能装 GeoLocation 类型的对象

  • 通俗理解:一个专门装地理位置的盒子,初始容量设为店铺数量,避免扩容开销


4. locations.add(new RedisGeoCommands.GeoLocation<>(...))
  • 含义:创建一个新的 GeoLocation 对象(单个店铺的地理位置),然后 add 放进上面的 locations 集合里

  • 通俗理解:把一个个 "地理位置" 放进 "盒子" 里,准备批量写入 Redis


5. stringRedisTemplate.opsForGeo().add(key, locations);
  • 作用:一次性把 locations 盒子里的所有数据,批量写入 Redis GEO 集合

  • 优势:比单条写入减少多次网络 IO,大幅提升导入效率

6.关键细节:
  • Redis Key 设计 :shop:geo:{typeId},不同类型的店铺存储在不同的 GEO 集合中,后续查询时按类型筛选更高效。

  • GeoLocation 对象:

    • member:店铺ID(后续查询结果中返回的标识)

    • Point:店铺的经纬度 (x, y)

  • 批量写入优化 :先构建好所有 GeoLocation 对象,再一次性调用 add(key, locations),避免多次网络IO,大幅提升导入效率。


三、核心技术点:Redis GEO

Redis GEO 是专门用于存储和查询地理位置数据的数据结构,核心命令包括:

  • GEOADD key longitude latitude member:添加地理位置

  • GEORADIUS key longitude latitude radius:按半径查询附近的成员

这段代码中,我们把每个类型的店铺都存入了对应 shop:geo:{typeId} 的 GEO 集合中,后续就可以直接用 GEORADIUS 命令,查询指定经纬度附近的该类型店铺。


四、总结

这段代码将数据库中的所有店铺按类型分组,批量构建为 GeoLocation 对象,并一次性写入 Redis GEO 结构,为后续实现"附近店铺"查询功能做数据准备。

相关推荐
邪修king3 小时前
Re:Linux 系统篇(三十五):进程间通信Chapter2:从匿名管道到进程池:Linux 进程间通信实战(深度理解「先描述,再组织」)
java·linux·运维
2301_777998343 小时前
ARP协议进阶:ARP缓存、RARP与ARP欺骗原理解析
linux·服务器·网络·网络协议·缓存
拆房老料3 小时前
【第四部分:Agentic 智能体设计模式】16. 一个 Prompt 搞不定复杂任务?试试 Prompt Chaining
java·前端·人工智能·设计模式·prompt
张张123y4 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
曹牧8 小时前
C#:空合并运算符
java·前端·数据库
布吉岛的石头9 小时前
Java 程序员第 50 阶段2:预训练的目标函数:自回归语言建模本质
java·开发语言·人工智能·深度学习·回归·transformer
golang学习记9 小时前
IDEA 2026年的玩法已经完全不同
java·ide·intellij-idea
紧跟先前的步伐10 小时前
Go AI Agent 实战 05|Temperature 与生成参数:让模型输出可控
java·人工智能·golang
金銀銅鐵10 小时前
[Java] 展示添加元素时 ArrayList 的内部变化
java·后端·ai编程
斌糖雪梨10 小时前
spring auth 核心流程详解
java·后端·spring