如何查询MongoDB返回完整文档但仅保留符合条件的子文档?
解决方案
方案1:使用$filter运算符(推荐,MongoDB 3.2及以上版本支持)
这是性能最优的实现方式,不需要拆分原数组,直接对comments字段做过滤,同时保留所有原文档字段:
db.yourCollectionName.aggregate([ // 第一步:筛选目标文档,这里示例按_id匹配,可按需替换查询条件 { $match: { _id: ObjectId("1234567890") } }, // 第二步:重写comments字段,仅保留用户为bob的评论 { $addFields: { comments: { $filter: { input: "$comments", cond: { $eq: ["$$this.user", "bob"] } } } } }, // 可选:如果不需要返回_id字段,可添加投影去掉 { $project: { _id: 0 } } ])
说明:如果是MongoDB 4.2及以上版本,$addFields可以替换为别名$set,效果完全一致。
方案2:$unwind + $match + $group 兼容方案(适用于MongoDB 3.2以下版本)
你之前用$unwind的方案缺了分组合并的步骤,补充后就可以还原原文档结构:
db.yourCollectionName.aggregate([ { $match: { _id: ObjectId("1234567890") } }, // 拆分comments数组为单条文档 { $unwind: "$comments" }, // 筛选出bob的评论 { $match: { "comments.user": "bob" } }, // 按原文档_id分组,还原其他字段,重新合并comments为数组 { $group: { _id: "$_id", author: { $first: "$author" }, text: { $first: "$text" }, details: { $first: "$details" }, category: { $first: "$category" }, comments: { $push: "$comments" } } }, // 可选:去掉返回结果中的_id字段 { $project: { _id: 0 } } ])
原方案问题说明
find/findOne投影中的$elemMatch本身设计就是仅返回第一个匹配的数组元素,无法返回所有匹配项- 单独使用
$unwind+$match只会输出拆分后的单条评论文档,必须配合$group阶段才能把匹配的评论重新合并为数组,同时还原原文档的其他字段
内容的提问来源于stack exchange,提问作者r.sch136
相关产品推荐
相关产品推荐

