You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB聚合:过滤嵌套数组内的目标记录

MongoDB 过滤嵌套数组并保留原文档结构的解决方案

问题场景

现有MongoDB集合中的文档结构如下:

{
 "cId":23456,
 "description":"car",
  "brand": [{
    "bId":23,
    "bName":"toyota",
     "model":[{
      "mName":"camry",
      "vId":"12"
      },
      {
      "mName":"corolla",
      "vId":"13"
      }]
   },{
    "bId":24,
    "bName":"honda",
     "model":[{
      "mName":"accord",
      "vId":"14"
      },
      {
      "mName":"civic",
      "vId":"15"
      }]
   }]
}

需要筛选出mName: civic的记录,最终输出需保留原文档层级,只保留包含目标model的brand,且该brand下仅保留符合条件的model,结果如下:

{
 "cId":23456,
 "description":"car",
  "brand": [{
    "bId":24,
    "bName":"honda",
     "model":[
      {
      "mName":"civic",
      "vId":"15"
      }]
   }]
}

解决方案(无需反复unwind)

可以通过聚合管道中的$filter与$map组合实现,避免多次unwind后分组的复杂操作:

db.collection.aggregate([
  // 先筛选出包含目标model的文档,减少后续处理量
  { $match: { "brand.model.mName": "civic" } },
  // 过滤brand数组,只保留包含目标model的品牌
  {
    $project: {
      cId: 1,
      description: 1,
      brand: {
        $filter: {
          input: "$brand",
          as: "brandItem",
          cond: { $in: ["civic", "$$brandItem.model.mName"] }
        }
      }
    }
  },
  // 对保留的品牌,过滤其model数组只保留符合条件的项
  {
    $addFields: {
      brand: {
        $map: {
          input: "$brand",
          as: "brandItem",
          in: {
            bId: "$$brandItem.bId",
            bName: "$$brandItem.bName",
            model: {
              $filter: {
                input: "$$brandItem.model",
                as: "modelItem",
                cond: { $eq: ["$$modelItem.mName", "civic"] }
              }
            }
          }
        }
      }
    }
  }
])

代码解释

  1. $match阶段:快速筛选出包含目标model的文档,避免对无关文档做后续处理,提升性能。
  2. $project阶段:用$filter过滤外层brand数组,只保留包含civic型号的品牌项。
  3. $addFields阶段:用$map遍历保留的品牌,对每个品牌的model数组再次做$filter,仅保留符合条件的型号记录。

更简洁的合并写法(MongoDB 3.6+)

可以将两个过滤步骤合并到同一个$project中:

db.collection.aggregate([
  { $match: { "brand.model.mName": "civic" } },
  {
    $project: {
      cId: 1,
      description: 1,
      brand: {
        $map: {
          input: {
            $filter: {
              input: "$brand",
              as: "brand",
              cond: { $in: ["civic", "$$brand.model.mName"] }
            }
          },
          as: "brand",
          in: {
            bId: "$$brand.bId",
            bName: "$$brand.bName",
            model: {
              $filter: {
                input: "$$brand.model",
                as: "model",
                cond: { $eq: ["$$model.mName", "civic"] }
              }
            }
          }
        }
      }
    }
  }
])

为什么不推荐多次unwind?

反复unwind嵌套数组后再分组,容易丢失原文档的层级关系,且需要多次$group操作,代码复杂度高,性能也远不如直接用$filter和$map的组合方案。

内容的提问来源于stack exchange,提问作者rjc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:32:10