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

MongoDB过滤嵌套文档数组并保留父字段 应使用find还是aggregate?

MongoDB数组过滤查询解决方案

直接使用aggregate即可实现需求,无需拆分数组后重新组装,$filter操作符可以直接完成数组元素过滤,且会自动保留父级原有字段,同时支持统计符合条件的文档数量和总大小。

完整查询语句

db.doc.aggregate([
  // 第一步:匹配符合条件的父文档,减少后续计算量
  {
    $match: {
      "UserDocuments.id": 1,
      "UserDocuments.documents.categories": "cat A"
    }
  },
  // 第二步:过滤documents数组,仅保留categories包含cat A的元素
  {
    $addFields: {
      "UserDocuments.documents": {
        $filter: {
          input: "$UserDocuments.documents",
          as: "doc",
          cond: { $in: ["cat A", "$$doc.categories"] }
        }
      }
    }
  },
  // 第三步:自动计算符合条件的文档数量和总大小
  {
    $addFields: {
      "UserDocuments.count": { $size: "$UserDocuments.documents" },
      "UserDocuments.totalSize": {
        $sum: "$UserDocuments.documents.size"
      }
    }
  }
])

方案说明

  • 之前使用$unwind拆分数组后没有做$group合并,所以会返回多条重复的父文档数据,本方案直接过滤数组,无需拆分,执行效率更高。
  • 使用$addFields而不是$project的优势是不需要手动声明所有要保留的字段,只会更新你指定的documents、count、totalSize三个字段,UserDocuments下的id等其他原有字段会自动保留,不会丢失。
  • 如果不需要统计count和totalSize,直接删除第三步的$addFields阶段即可。

可选find方案(仅过滤数组,不支持统计)

如果你不需要自动计算数量和总大小,用find也可以实现数组过滤:

db.doc.find(
  {
    "UserDocuments.id": 1,
    "UserDocuments.documents.categories": "cat A"
  },
  {
    "UserDocuments.id": 1,
    "UserDocuments.documents": {
      $filter: {
        input: "$UserDocuments.documents",
        as: "doc",
        cond: { $in: ["cat A", "$$doc.categories"] }
      }
    }
  }
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:06:01