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

如何通过MongoDB聚合框架统计未知技能的出现次数?

需求描述

给定MongoDB集合fighters中的文档如下:

[
  {
    _id: "N0001",
    name: "Bruce Lee",
    skills: ["karate", "jiu jitsu"],
  },
  {
    _id: "N0002",
    name: "Bruce Dee",
    skills: ["karate", "tae kwon do"],
  },
  {
    _id: "N0003",
    name: "Bruce See",
    skills: ["aikido", "jiu jitsu"],
  },
  {
    _id: "N0004",
    name: "Deuce Lee",
    skills: ["karate", "judo"],
  },
]

需要统计每种技能的出现次数,得到如下结果:

{
  karate: 3,
  jiu jitsu: 2,
  tae kwon do: 1,
  judo: 1,
  aikido: 1,
}

当前通过Node.js脚本实现,但希望完全用MongoDB聚合框架完成,避免客户端多次查询,且技能列表未知,无法预先硬编码。

聚合框架实现方案

直接使用以下聚合管道即可完成需求:

db.fighters.aggregate([
  // 拆分skills数组为单个技能文档
  { $unwind: "$skills" },
  // 按技能分组统计次数
  {
    $group: {
      _id: "$skills",
      count: { $sum: 1 }
    }
  },
  // 将统计结果整理为k-v格式的数组
  {
    $group: {
      _id: null,
      skillsCount: {
        $push: {
          k: "$_id",
          v: "$count"
        }
      }
    }
  },
  // 将数组转换为目标对象格式
  {
    $replaceRoot: {
      newRoot: { $arrayToObject: "$skillsCount" }
    }
  }
])

步骤说明:

  • $unwind:把每个文档的skills数组拆分为多条独立文档,每条仅包含一个技能,为后续单技能统计做准备。
  • 第一次$group:以技能名为分组键,用$sum:1统计每个技能的出现次数。
  • 第二次$group:将所有技能的统计结果聚合为一个包含k(技能名)和v(次数)的数组。
  • $replaceRoot + $arrayToObject:把数组格式的统计结果转换为目标对象,将数组中的k-v对映射为对象的键值对。

执行该聚合查询后,会直接返回符合要求的统计结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:30:15