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

MongoDB中如何对比数组并统计匹配项的文档数量?

解决MongoDB统计指定数组元素对应文档数的问题

嘿,我刚好处理过类似的统计需求,给你一个能直接解决问题的MongoDB聚合方案,完全符合你的期望输出。

先看完整的聚合查询代码,你可以直接替换集合名和目标数组使用:

const targetArray = ['A', 'B', '1'];

db.getCollection('mycollection').aggregate([
  // 第一步:先过滤出包含目标元素的文档,减少后续处理的数据量
  {
    $match: {
      locations: { $in: targetArray }
    }
  },
  // 第二步:把每个文档的locations数组拆成单个元素的独立文档
  {
    $unwind: "$locations"
  },
  // 第三步:只保留目标数组里的元素,过滤掉无关内容
  {
    $match: {
      locations: { $in: targetArray }
    }
  },
  // 第四步:按元素分组,统计每个元素对应的文档总数
  {
    $group: {
      _id: "$locations",
      count: { $sum: 1 }
    }
  },
  // 最后两步:把分组结果转换成你需要的键值对格式
  {
    $group: {
      _id: null,
      result: { $push: { k: "$_id", v: "$count" } }
    }
  },
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$result" }
    }
  }
])

每一步的作用说明:

  • 第一个$match:先筛选出locations数组包含目标数组中任意元素的文档,这样能减少后续要处理的数据量,提升查询效率。
  • $unwind:将每个文档的locations数组拆分成多个单元素文档,比如原文档{locations: ["A","B","C"]}会被拆成三个独立文档:{locations: "A"}、{locations: "B"}、{locations: "C"}。
  • 第二个$match:过滤掉不在目标数组里的元素(比如"C"、"D"这些),确保只统计你关心的元素。
  • 第一个$group:以locations的元素为分组键,统计每个元素出现的次数——这里的次数就是包含该元素的原文档总数,因为每个原文档unwind后每个元素只对应一次。
  • 最后两个阶段:把分组后的数组格式(比如[{_id: "A", count:2}, ...])转换成你需要的键值对对象,通过$push生成键值对数组,再用$arrayToObject转换为对象,最后用$replaceRoot把这个对象作为结果返回。

执行这个查询后,你会得到完全符合预期的结果:

{ "A" : 2, "B" : 1, "1" : 1 }

扩展:如果需要保留目标数组中无匹配的元素(显示count为0)

如果你的目标数组里有元素在集合中没有匹配到任何文档,上面的查询会自动忽略它。如果需要保留这些元素并显示count: 0,可以用下面的调整版:

const targetArray = ['A', 'B', '1', 'X'];

db.getCollection('mycollection').aggregate([
  // 先构造包含所有目标元素的初始文档
  {
    $documents: targetArray.map(item => ({ key: item }))
  },
  // 左连接原集合,匹配包含当前元素的文档并统计数量
  {
    $lookup: {
      from: "mycollection",
      let: { targetKey: "$key" },
      pipeline: [
        { $match: { $expr: { $in: ["$$targetKey", "$locations"] } } },
        { $count: "matched" }
      ],
      as: "matches"
    }
  },
  // 提取匹配数,无匹配则设为0
  {
    $addFields: {
      count: { $ifNull: [{ $arrayElemAt: ["$matches.matched", 0] }, 0] }
    }
  },
  // 转换为键值对对象
  {
    $group: {
      _id: null,
      result: { $push: { k: "$key", v: "$count" } }
    }
  },
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$result" }
    }
  }
])

这个版本的结果会包含所有目标元素,比如X会显示0:

{ "A" : 2, "B" : 1, "1" : 1, "X" : 0 }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:45:41