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

基于日期字段使用聚合将MongoDB文档拆分为多份文档

MongoDB按年份拆分含数组的文档并存入不同集合解决方案

问题分析

你用$match或$find没得到结果是因为这两个操作只能过滤现有文档,没法拆分文档内的数组、按字段重新分组生成新文档。要实现需求,需要结合MongoDB聚合管道处理数组和分组,再将结果写入对应年份的集合。

假设样例数据

先明确数据结构(以常见日期字段为例):

原文档:

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "flight_records": [
    {"flight_no": "CA123", "flight_date": ISODate("2020-03-15T10:00:00Z"), "passengers": 150},
    {"flight_no": "MU456", "flight_date": ISODate("2020-07-22T14:30:00Z"), "passengers": 180},
    {"flight_no": "CZ789", "flight_date": ISODate("2021-01-05T08:15:00Z"), "passengers": 120},
    {"flight_no": "CA321", "flight_date": ISODate("2022-11-30T16:45:00Z"), "passengers": 160},
    {"flight_no": "MU654", "flight_date": ISODate("2023-05-10T09:20:00Z"), "passengers": 190}
  ]
}

期望输出(每个年份一个独立文档):

// 2020年文档
{
  "year": 2020,
  "flight_records": [
    {"flight_no": "CA123", "flight_date": ISODate("2020-03-15T10:00:00Z"), "passengers": 150},
    {"flight_no": "MU456", "flight_date": ISODate("2020-07-22T14:30:00Z"), "passengers": 180}
  ]
}

解决方案步骤

1. 用聚合管道拆分并分组数据

执行以下聚合命令,将原文档拆分为按年份聚合的独立文档:

db.your_source_collection.aggregate([
  // 把flight_records数组拆分为单个记录的文档
  { $unwind: "$flight_records" },
  // 从航班日期中提取年份
  {
    $addFields: {
      "flight_year": { $year: "$flight_records.flight_date" }
    }
  },
  // 按年份分组,重新收集同一年的航班记录
  {
    $group: {
      _id: "$flight_year",
      flight_records: { $push: "$flight_records" }
    }
  },
  // 可选:把_id重命名为year,让文档结构更清晰
  {
    $project: {
      _id: 0,
      year: "$_id",
      flight_records: 1
    }
  }
])

2. 将分组结果存入对应年份的集合

因为MongoDB的$out操作只能输出到单个集合,所以需要用客户端代码遍历聚合结果,分别写入对应年份的集合(比如flight_2020、flight_2021)。

用Mongo Shell脚本实现:
// 执行聚合查询获取结果游标
const yearGroups = db.your_source_collection.aggregate([
  { $unwind: "$flight_records" },
  { $addFields: { "flight_year": { $year: "$flight_records.flight_date" } } },
  { $group: { _id: "$flight_year", flight_records: { $push: "$flight_records" } } },
  { $project: { _id: 0, year: "$_id", flight_records: 1 } }
]);

// 遍历游标,写入对应集合
yearGroups.forEach(groupDoc => {
  const targetCollection = `flight_${groupDoc.year}`;
  db.getCollection(targetCollection).insertOne(groupDoc);
});
用Node.js代码实现(适合批量处理):
const { MongoClient } = require('mongodb');

async function splitFlightData() {
  const client = await MongoClient.connect('mongodb://localhost:27017/your_database_name');
  const db = client.db();

  // 执行聚合
  const cursor = db.collection('your_source_collection').aggregate([
    { $unwind: "$flight_records" },
    { $addFields: { "flight_year": { $year: "$flight_records.flight_date" } } },
    { $group: { _id: "$flight_year", flight_records: { $push: "$flight_records" } } },
    { $project: { _id: 0, year: "$_id", flight_records: 1 } }
  ]);

  // 逐个写入目标集合
  await cursor.forEach(async doc => {
    const collName = `flight_${doc.year}`;
    await db.collection(collName).insertOne(doc);
  });

  await client.close();
}

splitFlightData().catch(console.error);

关键说明

  • $unwind:将数组拆分为单个元素的文档,为后续按年份分组做准备。
  • 若你的日期是字符串格式,需要先用$toDate转换为Date类型再提取年份。
  • 写入集合时,若目标集合不存在,MongoDB会自动创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 07:35:21