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

MongoDB中如何对嵌套对象递归应用投影并生成路径字段?

MongoDB 多层嵌套文档的递归投影与路径计算实现

我在MongoDB中有如下多层嵌套的数据结构:

{
    _id: ObjectId("123"),
    name: "Top level",
    someData: "hello world",
    parent: null,
    children: {
        "456": {
            _id: ObjectId("456"),
            name: "Nested Obj",
            parent: "123",
            someData: "lorem ipsum",
            children: {
                "963": {
                    _id: ObjectId("963"),
                    name: "2nd level nesting",
                    parent: "456",
                    someData: "some data",
                    children: {}
                }
            }
        },
        "798": {
            _id: ObjectId("798"),
            parent: "123",
            name: "Another entry",
            someData: "more data here",
            children: {},
        }
    }
}

需要实现两个需求:

  • 对所有嵌套对象递归应用投影,仅保留_id和name字段
  • 创建计算字段path,存储每个对象的访问路径(顶层路径为空数组,子节点路径包含所有父节点的_id)

期望查询结果如下:

{
    _id: ObjectId("123"),
    name: "Top level",
    path: [],
    children: {
        "456": {
            _id: ObjectId("456"),
            name: "Nested Obj",
            path: ["123"],
            children: {
                "963": {
                    _id: ObjectId("963"),
                    name: "2nd level nesting",
                    path: ["123", "456"],
                    children: {}
                }
            }
        },
        "798": {
            _id: ObjectId("798"),
            name: "Another entry",
            path: ["123"],
            children: {},
        }
    }
}

实现方案

可以通过MongoDB 4.4+版本支持的$function自定义递归函数,结合聚合框架完成需求:

db.collection.aggregate([
  {
    $addFields: {
      path: [],
      children: {
        $function: {
          body: function(children, parentPath) {
            // 递归处理单个节点的函数
            const processNode = (node, currentPath) => {
              // 执行投影,只保留指定字段
              const processedNode = {
                _id: node._id,
                name: node.name,
                path: currentPath,
                children: {}
              };
              // 遍历子节点,递归处理
              Object.keys(node.children).forEach(key => {
                processedNode.children[key] = processNode(
                  node.children[key],
                  [...currentPath, node._id.toString()]
                );
              });
              return processedNode;
            };

            const processedChildren = {};
            // 遍历顶层children中的所有节点
            Object.keys(children).forEach(key => {
              processedChildren[key] = processNode(
                children[key],
                [...parentPath, this._id.toString()]
              );
            });
            return processedChildren;
          },
          args: ["$children", "$path"],
          lang: "js"
        }
      }
    }
  },
  // 顶层文档投影,过滤不需要的字段
  {
    $project: {
      _id: 1,
      name: 1,
      path: 1,
      children: 1
    }
  }
])

说明

  1. 递归投影:自定义的processNode函数会对每个节点只保留_id、name、children字段,过滤掉someData、parent等不需要的内容
  2. 路径计算:每个节点的path由父节点的路径加上父节点的_id拼接而成,顶层节点的path初始化为空数组
  3. 版本要求:必须使用MongoDB 4.4及以上版本,因为$function是该版本引入的特性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:15:11