MongoDB如何筛选对象数组中status为Pending的嵌套文档
解决MongoDB嵌套数组元素筛选问题
针对你遇到的场景:需要返回用户文档,但仅保留todos数组中status为"Pending"的元素,而非返回包含匹配项的完整用户文档,以下是可行方案:
示例文档
{ "_id": ObjectId("123"), "name": "Alice", "todos": [ {"task": "Buy milk", "status": "Pending"}, {"task": "Finish report", "status": "Completed"}, {"task": "Call mom", "status": "Pending"} ] }
期望返回结果
{ "_id": ObjectId("123"), "name": "Alice", "todos": [ {"task": "Buy milk", "status": "Pending"}, {"task": "Call mom", "status": "Pending"} ] }
正确解决方案:聚合管道+$filter操作符
这是最精准灵活的方式,能过滤数组中所有符合条件的元素:
db.users.aggregate([ // 先筛选出至少包含一个Pending待办的用户(可选,减少后续处理数据量) { $match: { "todos.status": "Pending" } }, // 替换todos数组,仅保留status为Pending的元素 { $addFields: { todos: { $filter: { input: "$todos", // 指定待过滤的数组 cond: { $eq: ["$$this.status", "Pending"] } // 过滤条件,$$this代表数组当前遍历元素 } } } } ])
替代方案:用$project指定返回字段
若需明确控制返回的字段列表,可替换$addFields为$project:
db.users.aggregate([ { $match: { "todos.status": "Pending" } }, { $project: { name: 1, // 保留name字段 todos: { $filter: { input: "$todos", cond: { $eq: ["$$this.status", "Pending"] } } } } } ])
为什么你之前的方法无效?
- 直接使用
db.users.find({"todos.status": "Pending"}):仅会返回包含至少一个Pending待办的用户文档,但不会过滤数组内不符合条件的元素。 - 使用
find搭配$elemMatch投影:比如db.users.find({"todos.status": "Pending"}, {todos: {$elemMatch: {status: "Pending"}}}),仅会返回数组中第一个匹配的元素,而非所有符合条件的项。
内容的提问来源于stack exchange,提问作者Itti'Z Wallet
相关产品推荐
相关产品推荐

