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

如何在Node.js Express中通过ID查询MongoDB文件夹及其子项?

问题

我在MongoDB中存储了如下层级结构的文件/文件夹数据:

[
  {
    "_id": 1,
    "name": "ABC",
    "parentID": null
  },
  {
    "_id": 2,
    "name": "ABC.txt",
    "parentID": 1
  },
  {
    "_id": 3,
    "name": "ABCD",
    "parentID": 1
  },
  {
    "_id": 4,
    "name": "ABC 3",
    "parentID": 3
  },
  {
    "_id": 5,
    "name": "ABCDFE",
    "parentID": null
  }
]

需要在Node.js Express中编写查询,根据指定文件夹ID(比如ID为1的文件夹),获取该文件夹及其所有子项,忽略其他顶级文件夹(比如ID为5的文件夹),期望返回结果如下:

[
  {
    "_id": 1,
    "name": "ABC",
    "parentID": null
  },
  {
    "_id": 2,
    "name": "ABC.txt",
    "parentID": 1
  },
  {
    "_id": 3,
    "name": "ABCD",
    "parentID": 1
  },
  {
    "_id": 4,
    "name": "ABC 3",
    "parentID": 3
  }
]

当前代码如下:

exports.getProofFolderById = async (req, res, next) => {
  const file = await Proof.find({ _id: req.params.id})
  if(!file) {
    next(new Error("Folder not found!!!"))
  }
  res.status(200).json({
    success: true,
    file
  })
}

恳请帮忙修改代码实现需求,谢谢❤️

解决方案

要实现获取指定文件夹及其所有层级子项的需求,可利用MongoDB的聚合查询,通过$graphLookup操作符递归查询所有子节点,修改后的代码及说明如下:

修改后的完整代码

exports.getProofFolderById = async (req, res, next) => {
  const folderId = req.params.id;

  // 先验证目标文件夹是否存在
  const targetFolder = await Proof.findById(folderId);
  if (!targetFolder) {
    return next(new Error("Folder not found!!!"));
  }

  // 聚合查询获取当前文件夹及所有子项
  const result = await Proof.aggregate([
    // 匹配目标文件夹
    { $match: { _id: folderId } },
    // 递归查询所有层级的子节点
    {
      $graphLookup: {
        from: "proofs", // 对应MongoDB集合名称,需与你的Model集合名一致
        startWith: "$_id",
        connectFromField: "_id",
        connectToField: "parentID",
        as: "children",
        maxDepth: 100 // 根据实际层级调整最大递归深度
      }
    },
    // 展开子节点数组为平级文档
    { $unwind: { path: "$children", preserveNullAndEmptyArrays: true } },
    // 将子节点或原文件夹作为根文档
    {
      $replaceRoot: {
        newRoot: { $cond: { if: "$children", then: "$children", else: "$$ROOT" } }
      }
    },
    // 合并目标文件夹本身到结果集
    { $unionWith: { coll: "proofs", pipeline: [{ $match: { _id: folderId } }] } },
    // 去重,避免目标文件夹重复出现
    { $group: { _id: "$_id", doc: { $first: "$$ROOT" } } },
    { $replaceRoot: { newRoot: "$doc" } },
    // 可选:按parentID排序,保持层级展示顺序
    { $sort: { parentID: 1, _id: 1 } }
  ]);

  res.status(200).json({
    success: true,
    files: result
  });
};

关键逻辑说明

  1. 文件夹存在性校验:通过findById先确认目标文件夹存在,避免无效查询。
  2. $graphLookup递归查询:核心操作,从指定集合中递归查找所有以当前文件夹_id为parentID的节点,以及这些节点的子节点,直到达到maxDepth限制。
  3. 结果格式化:通过$unwind展开嵌套的子节点数组,$unionWith将原文件夹文档加入结果,最后去重并排序,得到与期望一致的平级结构。

注意事项

  • 确保from字段的值是你的MongoDB集合实际名称(通常Model对应的集合名为小写复数,比如Proof模型对应proofs集合)。
  • maxDepth可根据业务场景调整,防止无限递归。
  • 若需要返回嵌套层级结构,可去掉$unwind及后续的平级处理步骤,直接返回包含children字段的嵌套文档。

内容的提问来源于stack exchange,提问作者Đạt Huỳnh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:15:40