MongoDB子文档过滤问题:如何仅返回匹配的嵌套子文档
如何在MongoDB中仅返回匹配指定sub_id的subscriptions子文档
这是个很常见的MongoDB嵌套数组筛选问题——普通的find查询只会判断整个文档是否满足条件,不会对嵌套的数组元素做过滤,所以会返回完整的subscriptions数组。下面给你两种可行的解决方案,都能得到你期望的结果:
方法一:使用聚合管道(推荐,扩展性更强)
通过聚合管道的$match和$project阶段组合,先过滤出符合条件的文档,再筛选数组中匹配的元素:
db.collection.aggregate([ // 第一步:先筛选出包含目标sub_id的文档,减少后续处理的数据量 { $match: { "subscriptions.sub_id": "5a4df654b9799b79147f9361" } }, // 第二步:投影并筛选subscriptions数组 { $project: { email: 1, username: 1, subscriptions: { $filter: { input: "$subscriptions", // 要筛选的数组 as: "sub", // 数组元素的别名 cond: { $eq: ["$$sub.sub_id", "5a4df654b9799b79147f9361"] } // 匹配条件 } } } } ])
说明:
$match阶段先缩小处理范围,只保留包含目标sub_id的文档,提升查询效率;$filter操作符会遍历subscriptions数组,只保留sub_id匹配的元素,其他字段(email、username、_id)会原样保留。
方法二:使用find配合投影筛选(更简洁)
如果你不想用聚合管道,MongoDB 3.2及以上版本支持直接在find的投影参数中使用$filter,实现同样的效果:
db.collection.find( // 查询条件:匹配包含目标sub_id的文档 { "subscriptions.sub_id": "5a4df654b9799b79147f9361" }, // 投影规则:筛选subscriptions数组并保留其他字段 { email: 1, username: 1, subscriptions: { $filter: { input: "$subscriptions", as: "sub", cond: { $eq: ["$$sub.sub_id", "5a4df654b9799b79147f9361"] } } } } )
注意:
- 不要使用
$elemMatch——它只能返回数组中第一个匹配的元素,而你需要保留所有匹配的子文档,所以$filter才是正确的选择; - 两种方法都会返回你期望的结果:仅包含匹配指定
sub_id的subscriptions子文档,同时保留其他字段不变。
内容的提问来源于stack exchange,提问作者AlpeshVasani
相关产品推荐
相关产品推荐

