如何在MongoDB中关联Node与Organisation集合查询父子层级关系?
在MongoDB中关联Node与Organisation集合并查询父子层级关系
根据你的集合结构和层级需求,我们可以通过MongoDB的聚合管道(尤其是$graphLookup递归查询)来整合Organisation和Node的层级,生成带嵌套children的树形结构。以下是具体实现步骤:
整体思路
先递归构建Organisation的完整层级树,再关联对应的Node层级树,最后将Node树挂载到对应的底层Organisation的children中,形成顶层Org→子Org→底层Org→顶层Node→子Node→底层Node的完整链路。
完整聚合查询代码
db.Organisation.aggregate([ // 1. 递归构建Organisation的层级树 { $graphLookup: { from: "Organisation", startWith: "$_id", connectFromField: "_id", connectToField: "_parentOrg", as: "children", depthField: "depth" // 可选:记录每个节点的层级深度 } }, // 筛选出顶层Organisation(无_parentOrg字段) { $match: { _parentOrg: { $exists: false } } }, // 2. 关联并构建对应Organisation的Node层级树 { $lookup: { from: "Node", let: { currentOrgId: "$_id" }, pipeline: [ // 匹配关联当前Organisation的顶层Node(含_organisation字段) { $match: { $expr: { $eq: ["$_organisation", "$$currentOrgId"] } } }, // 递归查询当前Node的所有子Node { $graphLookup: { from: "Node", startWith: "$_id", connectFromField: "_id", connectToField: "_parentNode", as: "children" } }, // 整理Node的输出结构 { $project: { _id: 1, name: 1, children: { $map: { input: "$children", as: "childNode", in: { _id: "$$childNode._id", name: "$$childNode.name", children: "$$childNode.children" } } } } } ], as: "linkedNodes" } }, // 3. 将Node树整合到Organisation的层级中 { $addFields: { children: { $map: { input: "$children", as: "childOrg", in: { _id: "$$childOrg._id", name: "$$childOrg.name", children: { // 把当前Organisation对应的Node树添加到子节点列表 $concatArrays: [ "$$childOrg.children", { $filter: { input: "$linkedNodes", cond: { $eq: ["$$this._organisation", "$$childOrg._id"] } } } ] } } } } } }, // 4. 整理最终输出字段 { $project: { _id: 1, name: 1, children: 1 } } ])
关键步骤说明
递归构建Organisation层级:
使用$graphLookup遍历所有子Organisation,自动生成每个Org的children列表,再通过$match筛选出顶层Org(无_parentOrg)作为树形结构的根节点。关联并构建Node层级:
通过$lookup关联当前Org对应的顶层Node,再对每个Node用$graphLookup递归查询子Node,生成完整的Node树形结构,确保每个Node都带有自己的children列表。整合Org与Node层级:
用$map和$concatArrays将每个底层Organisation对应的Node树添加到该Org的children数组中,让整个层级链完整闭合。输出结构整理:
最后通过$project只保留需要的_id、name、children字段,输出结构统一,方便后续前端构建树形组件。
性能优化建议
- 给
_parentOrg、_parentNode、_organisation这三个字段创建单字段索引,大幅提升递归查询的速度。 - 如果不需要无限层级,可以在
$graphLookup中添加maxDepth参数限制递归深度。
内容的提问来源于stack exchange,提问作者Yiffany
相关产品推荐
相关产品推荐

