如何在MongoDB中查询子数组含指定ID且孙文档匹配条件的文档
解决MongoDB嵌套数组匹配及提取目标孙文档的问题
原查询失效的原因及修复
你写的查询返回0条结果,核心是两个问题:
- 错误的类型转换:集合里
kids._id是普通字符串(如'Test1'),不是MongoDB的ObjectId类型,所以不能用ObjectId('Test1'),直接写字符串值即可。 - 数组条件未关联:原查询的两个条件是分别匹配
kids数组中的任意元素,可能出现一个kid匹配_id: 'Test1',另一个kid匹配grandkids.name: 'Bloh',但没有同一个kid同时满足两个条件的情况。必须用$elemMatch把两个条件绑定到同一个kids元素上。
修复后的查询可以正确找到Parent2文档:
{ "kids": { "$elemMatch": { "_id": "Test1", "grandkids.name": "Bloh" } } }
仅返回匹配的孙文档
如果要直接输出符合条件的孙文档(而非整个父文档),用聚合管道实现,推荐两种方式:
方式1:展开数组逐步筛选
适合需要明确处理每一层数组的场景:
db.collection.aggregate([ // 先筛选出包含目标kid的父文档 { $match: { "kids": { "$elemMatch": { "_id": "Test1", "grandkids.name": "Bloh" } } } }, // 展开kids数组 { $unwind: "$kids" }, // 筛选出符合条件的kid { $match: { "kids._id": "Test1", "kids.grandkids.name": "Bloh" } }, // 展开grandkids数组 { $unwind: "$kids.grandkids" }, // 筛选出目标孙文档 { $match: { "kids.grandkids.name": "Bloh" } }, // 只保留孙文档的字段 { $project: { _id: 0, name: "$kids.grandkids.name" } } ])
方式2:用数组过滤直接提取(更简洁)
通过$filter直接定位目标元素,无需多次展开数组:
db.collection.aggregate([ // 先筛选出符合条件的父文档 { $match: { "kids": { "$elemMatch": { "_id": "Test1", "grandkids.name": "Bloh" } } } }, // 过滤出匹配的kid { $addFields: { matchedKid: { $first: { $filter: { input: "$kids", cond: { $and: [ { $eq: ["$$this._id", "Test1"] }, { $in: ["Bloh", "$$this.grandkids.name"] } ] } } } } } }, // 过滤出匹配的孙文档 { $addFields: { matchedGrandkid: { $first: { $filter: { input: "$matchedKid.grandkids", cond: { $eq: ["$$this.name", "Bloh"] } } } } } }, // 将孙文档作为根文档返回 { $replaceRoot: { newRoot: "$matchedGrandkid" } }, // 可选:移除自动生成的_id { $project: { _id: 0 } } ])
两种方式最终都会返回:
{ "name": "Bloh" }
内容的提问来源于stack exchange,提问作者Orion
相关产品推荐
相关产品推荐

