You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用spring-data-mongo计算MongoDB 3.2版本中文档树结构的深度

MongoDB 3.2版本树形结构深度统计实现方案

因为MongoDB 3.2不支持$graphLookup递归聚合算子,所以只能结合业务逻辑实现需求,以下是两种可行方案:

方案一:分批次按根节点查询(推荐,内存占用低)

适合数据量较大、树深度较低的场景,不需要全量拉取所有数据:

  • 先查询所有parent_id为null的根节点,获取每个根节点的name、rootId和id
  • 对每个根节点单独计算对应树的深度:
    1. 初始化深度为1,当前层节点ID列表为根节点ID
    2. 循环查询rootId匹配、parent_id属于当前层ID列表的所有子节点ID,作为下一层节点列表
    3. 若下一层列表不为空,深度+1,将当前层替换为下一层后继续循环;若为空则终止循环,当前深度就是该树的总深度
  • 汇总所有根节点的统计结果生成报表

核心代码示例(spring-data-mongo):

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

// 树节点实体类示例
class TreeNode {
    private String id;
    private String name;
    private String rootId;
    private String parent_id;
    // 省略getter、setter
}

// 统计结果实体类示例
class TreeDepthStat {
    private String rootName;
    private String rootId;
    private Integer totalDepth;
    // 省略getter、setter
}

public List<TreeDepthStat> statTreeDepth(MongoTemplate mongoTemplate) {
    // 查询所有根节点
    Query rootQuery = Query.query(Criteria.where("parent_id").is(null));
    List<TreeNode> rootNodes = mongoTemplate.find(rootQuery, TreeNode.class);
    List<TreeDepthStat> result = new ArrayList<>();

    for (TreeNode root : rootNodes) {
        int depth = 1;
        List<String> currentLevelIds = Collections.singletonList(root.getId());
        while (true) {
            // 只查子节点ID,减少数据传输
            Query childQuery = Query.query(Criteria.where("rootId").is(root.getRootId())
                    .and("parent_id").in(currentLevelIds))
                    .fields().include("id");
            List<String> nextLevelIds = mongoTemplate.find(childQuery, TreeNode.class)
                    .stream()
                    .map(TreeNode::getId)
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(nextLevelIds)) {
                break;
            }
            depth++;
            currentLevelIds = nextLevelIds;
        }
        // 封装统计结果
        TreeDepthStat stat = new TreeDepthStat();
        stat.setRootName(root.getName());
        stat.setRootId(root.getRootId());
        stat.setTotalDepth(depth);
        result.add(stat);
    }
    return result;
}

优化建议:给rootId和parent_id加联合索引,加快子节点查询速度,索引创建语句:db.tree.createIndex({rootId:1, parent_id:1})

方案二:全量拉取内存计算

适合数据量较小的场景,实现更简单,查询次数少:

  • 全量拉取tree集合所有节点数据,按rootId分组
  • 对每个分组的节点列表,用BFS广度优先遍历或者递归计算最大深度
  • 关联对应根节点的名称后汇总生成统计结果

内容的提问来源于stack exchange,提问作者aditya tolety

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:24:02