MongoDB如何按条件递归统计所有子节点数量?
如何按条件递归统计所有子节点中type为B的数量?
我来帮你解决这个递归统计子节点数量的问题!你之前尝试用$graphLookup但不知道怎么加条件过滤,其实MongoDB提供了专门的参数来实现这个需求,下面是两种可行的解决方案,你可以根据场景选择:
方案一:递归查找时直接过滤(更高效)
这种方法在$graphLookup阶段就筛选出符合type: "B"的子节点,避免加载不必要的数据,适合大数据量场景:
modelName.aggregate([ { $graphLookup: { from: "modelName", startWith: "$id", connectFromField: "id", connectToField: "parentId", as: "matchingChildren", // 关键参数:递归查找时只匹配type为B的节点 restrictSearchWithMatch: { type: "B" } } }, { // 统计符合条件的子节点数量 $addFields: { childBCount: { $size: "$matchingChildren" } } }, { // 保留需要的字段,去掉临时数组 $project: { id: 1, parentId: 1, type: 1, childBCount: 1 } } ]).allowDiskUse(true);
各阶段说明:
$graphLookup阶段:通过restrictSearchWithMatch参数,在递归遍历所有子节点的过程中,只将type为"B"的后代节点收集到matchingChildren数组中,这正是你需要的“带条件递归查找”。$addFields阶段:使用$size操作符计算matchingChildren数组的长度,得到该节点的childBCount值。$project阶段:只保留最终需要的字段,移除临时的matchingChildren数组,输出你期望的结构。
方案二:先获取所有子节点再过滤(更灵活)
如果之后需要对所有子节点做其他处理,也可以先获取全部子节点,再用$filter筛选出符合条件的节点:
modelName.aggregate([ { $graphLookup: { from: "modelName", startWith: "$id", connectFromField: "id", connectToField: "parentId", as: "children" } }, { // 从所有子节点中过滤出type为B的元素 $addFields: { matchingChildren: { $filter: { input: "$children", cond: { $eq: ["$$this.type", "B"] } } } } }, { // 统计过滤后的节点数量 $addFields: { childBCount: { $size: "$matchingChildren" } } }, { // 整理输出字段 $project: { id: 1, parentId: 1, type: 1, childBCount: 1 } } ]).allowDiskUse(true);
注意点:
你之前尝试在$graphLookup中使用match参数,但MongoDB的$graphLookup并没有这个参数,正确的条件过滤参数是restrictSearchWithMatch,用来限制递归查找时匹配的文档。
这两种方案都能得到你期望的输出结果:节点1的childBCount为3,节点2的为1,其余节点为0。
内容的提问来源于stack exchange,提问作者Prakash Naidu
相关产品推荐
相关产品推荐

