MongoDB聚合查询多级嵌套数组过滤及结构保留问题求助
多级嵌套数组过滤解决方案(保留原结构/恢复结构)
针对你的MongoDB多级嵌套数组过滤需求,以下两种方案分别实现保留原结构过滤和**$unwind后恢复结构**:
方案1:用$map+$filter逐层过滤(无需$unwind,保留原结构)
你的二级list是数组套数组的结构,直接用$filter会因层级路径问题失效,需逐层遍历+筛选:
db.runoob.aggregate([ // 匹配顶层文档,缩小处理范围 { $match: { $or: [ { name: 1, "list.name": 11 }, { name: 6, "list.name": 12 } ] } }, // 逐层过滤嵌套数组 { $project: { id: 1, name: 1, list: { $filter: { input: "$list", as: "topItem", // 筛选顶层list中符合条件的元素 cond: { $or: [ { $and: [{ $in: ["$$topItem.id", [11, 12]] }, { $eq: ["$$topItem.name", 11] }] }, { $and: [{ $in: ["$$topItem.id", [61, 62]] }, { $eq: ["$$topItem.name", 12] }] } ] }, // 构造筛选后的顶层list元素,同时处理内层嵌套数组 in: { id: "$$topItem.id", name: "$$topItem.name", list: { // 先遍历内层的数组套数组,过滤每个子数组中name=111的元素 $map: { input: "$$topItem.list", as: "subArray", in: { $filter: { input: "$$subArray", as: "innerItem", cond: { $eq: ["$$innerItem.name", 111] } } } }, // 可选:移除内层list中为空的子数组 $filter: { input: { $map: { input: "$$topItem.list", as: "subArray", in: { $filter: { input: "$$subArray", as: "innerItem", cond: { $eq: ["$$innerItem.name", 111] } } } } }, as: "filteredSubArr", cond: { $gt: [{ $size: "$$filteredSubArr" }, 0] } } } } } } } } ])
核心说明:
- 内层
list是数组套数组结构,需先用$map遍历每个子数组,再用$filter筛选子数组内的目标元素 - 最后可选加一层
$filter,移除内层list中为空的子数组(按需启用)
方案2:$unwind后恢复原结构
如果已用$unwind打散数组,可通过$group逐层聚合恢复嵌套结构:
db.runoob.aggregate([ // 打散所有嵌套数组 { $unwind: "$list" }, { $unwind: "$list.list" }, { $unwind: "$list.list" }, // 匹配目标数据 { $match: { $or: [ { name: 1, "list.name": 11, "list.list.name": 111 }, { name: 6, "list.name": 12, "list.list.name": 111 } ] } }, // 第一步:聚合最内层数组 { $group: { _id: { docId: "$_id", topId: "$list.id", topName: "$list.name", docName: "$name" }, innerList: { $push: "$list.list" } } }, // 第二步:聚合顶层list数组 { $group: { _id: { docId: "$_id.docId", docName: "$_id.docName" }, list: { $push: { id: "$_id.topId", name: "$_id.topName", list: ["$innerList"] // 恢复数组套数组的原始结构 } } } }, // 第三步:恢复顶层文档字段 { $project: { _id: "$_id.docId", name: "$_id.docName", list: 1 } } ])
核心说明:
$group的_id需包含上一层级的唯一标识,确保聚合后结构与原始数据一致- 最后通过
$project恢复顶层文档的原始字段名(如id、name)
内容的提问来源于stack exchange,提问作者周维明
相关产品推荐
相关产品推荐

