Bootstrap

redis存储树结构数据

本文主要讲解两方面内容:1.redis如何存储树结构数据。2.java操作redis时选取哪种序列化器。

1. redis如何存储树结构数据

先抛出结论,树结构数据在redis中的存储形式如下:树结构数据在redis中的存储形式

1.1 前置条件

  1. spring-boot-starter-data-redis(2.1.8)
  2. fastjson(1.2.61)
  3. redis可视化工具 Redis Desktop Manager

1.2 树结构数据在redis中的存储形式(数据结构)

在这里插入图片描述
假设有如上典型的组织机构数据,前端需要按层级展示,分层级查询指定节点的子集。

1.2.1 redis中Key的设计

redisKey={NAME_SPACE}:{level}:{parentId}
NAME_SPACE:该数据所在命名空间
level:当前层级
parentId:父节点id,可为空

1.2.2 查询
  1. 按层级查询:输入指定层级,返回该层级下的所有节点列表

入参:

{
	"level":3
}

返回:

[
    {
        "nodeId": "010101",
        "nodeName": "人事部"
    },
    {
        "nodeId": "010102",
        "nodeName": "技术部"
    },
    {
        "nodeId": "010301",
        "nodeName": "人事部"
    },
    {
        "nodeId": "010202",
        "nodeName": "技术部"
    },
    {
        "nodeId": "010201",
        "nodeName": "人事部"
    }
]
  1. 查询指定节点的所有子节点:输入该节点id和当前层级

入参:

{
	"nodeId":"0102",
	"level":2
}

返回:

[
    {
        "nodeId": "010202",
        "nodeName": "技术部"
    },
    {
        "nodeId": "010201",
        "nodeName": "人事部"
    }
]
1.2.3 后台实现

主要代码:

/**
     * 查询 指定层级下某个父节点的所有子节点
     *
     * @param level    层级
     * @param parentId 父节点id,为空时查询该层级下所有节点
     * @return 指定层级下某个父节点的所有子节点
     */
    @SuppressWarnings("unchecked")
    public List<OrgBean> getSubTree(int level, @Nullable String parentId) {
   
        List<OrgBean> beanList;
        if (StringUtils.isBlank(parentId) && level != 1) {
   
            //parentId 为空,模糊匹配查询
            beanList = patternSearch(level);
        } else {
   
            //parentId 不为空,精确匹配查询
            beanList = exactlySearch(level, parentId);
        }
        return beanList;
    }

    @SuppressWarnings("unchecked")
    private List<OrgBean> patternSearch(int level) {
   
        //SCAN 0 MATCH {NAME_SPACE}:{level}:* COUNT 10000
        String pattern = getRedisKey("*", level);
        logger.info("redisKey:{}", pattern);
        List<String> keys = (List<String>) redisTemplate.execute(connection -> {
   
            List<String> keyStrList = new ArrayList<>();
            RedisKeyCommands keysCmd = connection.keyCommands();
            //采用 SCAN 命令,迭代遍历所有key
            Cursor<byte[]> cursor = keysCmd.scan(ScanOptions.scanOptions().match(pattern).count(10000L).build());
            while (cursor
;