MongoDB使用$redact过滤二级嵌套数组匹配ID条目的问题
问题原因
原有写法失效的核心原因是:用$eq直接对比数组类型的authorIds和数值类型的目标ID,二者类型不匹配永远返回false,自然过滤不掉不匹配的条目。而且$redact是递归遍历文档所有层级的语法,针对这种固定二级嵌套数组的过滤场景,用$filter更简单直观,完全不需要$unwind+$group。
最优解决方案(推荐,无unwind/group)
直接在$project阶段用$filter对articles数组做过滤,判断条件用$in检查目标ID是否在authorIds数组内即可:
db.collection.aggregate([ { "$project": { title: 1, articles: { $filter: { input: "$articles", as: "item", cond: { $in: [2, "$$item.authorIds"] // 这里替换成你要匹配的目标作者ID } } }, articleCount: { $size: { $filter: { input: "$articles", as: "item", cond: { $in: [2, "$$item.authorIds"] } } } } } } ])
如果是MongoDB 4.4及以上版本,可以用$let简化重复的过滤逻辑:
db.collection.aggregate([ { "$project": { title: 1, articles: { $let: { vars: { filteredArticles: { $filter: { input: "$articles", as: "item", cond: {$in: [2, "$$item.authorIds"]} } } }, in: { list: "$$filteredArticles", count: {$size: "$$filteredArticles"} } } } } } ])
如果你坚持要使用$redact实现
调整$cond的判断条件,用$in替换$eq,同时用$ifNull处理不存在authorIds的层级避免报错:
db.collection.aggregate([ { "$project": { title: 1, articles: 1, articleCount: {$size: "$articles"} } }, { "$redact": { "$cond": { "if": { "$or": [ { $in: [2, {$ifNull: ["$authorIds", []]}] // 匹配authorIds包含目标ID的条目 }, { $gte: ["$articleCount", 1] // 保留根层级文档 } ] }, "then": "$$DESCEND", "else": "$$PRUNE" } } } ])
注意:$redact是递归遍历所有层级的,如果你文档里还有其他嵌套层级也存在
authorIds字段,会被误过滤,非必要场景不推荐用这个方案。
内容的提问来源于stack exchange,提问作者GameAtrix1
相关产品推荐
相关产品推荐

