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 结构,为后续实现"附近店铺"查询功能做数据准备。

相关推荐
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【66】Graph 长期记忆
java·人工智能·spring
Javatutouhouduan2 小时前
Java面试大厂真题汇总!
java·java面试·java面试题·后端开发·java编程·java架构师·java八股文
maomao大哥闯天下2 小时前
K8s对象deployment、job、service应用详解
java·容器·kubernetes
闪电悠米2 小时前
黑马点评-优惠券秒杀-05_local_lock_cluster_problem
java·spring boot·redis·缓存
IronMurphy2 小时前
SSM拷打第二讲!!!
java·spring·mybatis
小江的记录本2 小时前
【JVM虚拟机】类加载机制:类加载全流程:加载→验证→准备→解析→初始化(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·算法·安全·spring·面试
千纸鹤の脉搏2 小时前
多线程的初步了解---进程与线程
java·开发语言·学习·线程
许彰午3 小时前
状态模式实战——Row对象的状态机
java·ui·状态模式
搬石头的马农3 小时前
Claude Code SpringBoot开发:从0到1搭建企业级项目的6个核心Skill
java·人工智能·spring boot·后端·ai编程