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

MongoDB聚合嵌套数组事件出现次数,重组原结构遇阻求助

统计嵌套数组中事件出现次数并还原原结构问题

需求描述

统计嵌套数组statuses.events_count中各事件的出现次数,同时保留原文档的结构。

输入示例

[
  {
    "statuses": [
      {
        "status": "allowed",
        "count": 3,
        "events_count": [
          "2001",
          "1001",
          "1001"
        ]
      }
    ],
    "date": "2022-09-10 15:00",
    "_id": "2022-09-10 15:00"
  }
]

期望输出

[
  {
    "statuses": [
      {
        "status": "allowed",
        "count": 3,
        "events_count": [
          {"type": "2001", "count": 1},
          {"type": "1001", "count": 2}
        ]
      }
    ],
    "date": "2022-09-10 15:00",
    "_id": "2022-09-10 15:00"
  }
]

尝试的聚合管道

db.collection.aggregate([
  {
    "$unwind": "$statuses"
  },
  {
    "$unwind": "$statuses.events_count"
  },
  {
    "$group": {
      "_id": {
        "event_count": "$statuses.events_count",
        "status": "$statuses.status",
        "date": "$date",
        "count": "$statuses.count"
      },
      "occurences": {
        "$sum": 1
      }
    }
  }
])

当前输出

[
  {
    "_id": {
      "count": 3,
      "date": "2022-09-10 15:00",
      "event_count": "2001",
      "status": "allowed"
    },
    "occurences": 1
  },
  {
    "_id": {
      "count": 3,
      "date": "2022-09-10 15:00",
      "event_count": "1001",
      "status": "allowed"
    },
    "occurences": 2
  }
]

问题

重新分组回原结构时遇到困难,按date分组并推回statuses数组后,得到两个status为allowed的条目,无法合并成一个。

解决方案

需要通过多轮分组逐步还原原结构,完整聚合管道如下:

db.collection.aggregate([
  // 展开外层的statuses数组
  { "$unwind": "$statuses" },
  // 展开每个status下的events_count数组
  { "$unwind": "$statuses.events_count" },
  // 第一步分组:统计每个事件类型的出现次数,保留关联元数据
  {
    "$group": {
      "_id": {
        "event_type": "$statuses.events_count",
        "status": "$statuses.status",
        "date": "$date",
        "status_count": "$statuses.count",
        "doc_id": "$_id"
      },
      "event_count": { "$sum": 1 }
    }
  },
  // 第二步分组:将同一状态下的统计事件合并为events_count数组
  {
    "$group": {
      "_id": {
        "status": "$_id.status",
        "date": "$_id.date",
        "status_count": "$_id.status_count",
        "doc_id": "$_id.doc_id"
      },
      "events_count": {
        "$push": {
          "type": "$_id.event_type",
          "count": "$event_count"
        }
      }
    }
  },
  // 第三步分组:将状态对象合并回statuses数组,还原原结构
  {
    "$group": {
      "_id": "$_id.doc_id",
      "date": { "$first": "$_id.date" },
      "statuses": {
        "$push": {
          "status": "$_id.status",
          "count": "$_id.status_count",
          "events_count": "$events_count"
        }
      }
    }
  },
  // 确保输出字段与原文档一致
  {
    "$project": {
      "_id": "$_id",
      "date": 1,
      "statuses": 1
    }
  }
])

逻辑说明

  1. 第一轮分组:精准统计每个事件类型在对应状态、日期下的出现次数,同步保留所有需要复用的元数据;
  2. 第二轮分组:将同一状态下的所有统计结果整理成events_count数组,形成单个完整的状态对象;
  3. 第三轮分组:按文档_id分组,将状态对象合并回statuses数组,完全还原原文档结构;
  4. $project阶段:确保输出字段与原文档匹配,避免多余字段干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:15:40