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

如何使用$graphLookup查询子引用模式集合并生成树形视图

子引用模式MongoDB集合树形结构查询方案

实现思路

你使用的子引用模式(父文档存储子文档引用)可以通过$graphLookup递归遍历所有层级子节点,再将扁平化的查询结果组装为嵌套树形结构即可。

完整聚合查询语句

假设你的集合名为products,以下是查询指定根节点(示例中为prod03)的完整语句:

db.products.aggregate([
  // 匹配查询根节点,可根据需求调整匹配条件
  { $match: { id: "3" } },
  // 递归查询所有后代节点
  {
    $graphLookup: {
      from: "products",
      startWith: "$children._id",
      connectFromField: "children._id",
      connectToField: "_id",
      as: "allDescendants",
      depthField: "nodeLevel"
    }
  },
  // 组装嵌套树形结构
  {
    $addFields: {
      children: {
        $function: {
          body: function(rootChildren, descendants) {
            // 构建节点映射表提升查找效率
            const nodeMap = {};
            descendants.forEach(item => {
              nodeMap[item._id.toString()] = {
                id: item.id,
                name: item.name,
                totalQty: item.totalQty,
                children: item.children
              }
            });
            // 递归构建子树
            const buildSubTree = (childList) => {
              return childList.map(child => {
                const nodeInfo = nodeMap[child._id];
                if (!nodeInfo) return { id: child._id, qty: child.qty };
                return {
                  id: nodeInfo.id,
                  name: nodeInfo.name,
                  qty: child.qty,
                  totalQty: nodeInfo.totalQty,
                  children: nodeInfo.children.length ? buildSubTree(nodeInfo.children) : []
                }
              })
            }
            return buildSubTree(rootChildren);
          },
          args: ["$children", "$allDescendants"],
          lang: "js"
        }
      }
    }
  },
  // 过滤输出指定字段
  {
    $project: {
      _id: 0,
      id: 1,
      name: 1,
      totalQty: 1,
      children: 1
    }
  }
])

适配场景说明

  1. 查询所有根节点:如果需要查询所有没有父级的根节点,将第一阶段的$match替换为以下逻辑即可:
// 收集所有被引用的子节点ID
{
  $group: {
    _id: null,
    allReferencedIds: { $addToSet: "$children._id" }
  }
},
// 匹配未被引用的文档作为根节点
{
  $lookup: {
    from: "products",
    pipeline: [
      {
        $match: {
          $expr: {
            $not: { $in: ["$_id", { $concatArrays: "$allReferencedIds" }] }
          }
        }
      }
    ],
    as: "rootList"
  }
},
{ $unwind: "$rootList" },
{ $replaceRoot: { newRoot: "$rootList" } }
  1. 低版本MongoDB兼容:如果你的MongoDB版本低于4.4不支持$function,可以保留allDescendants字段,在应用层按照上述函数逻辑组装树形结构即可。
  2. 深层级适配:默认$graphLookup最大递归深度为100,若你的数据层级超过100,执行聚合时添加allowDiskUse: true参数即可突破限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:57:03