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

MongoDB Node环境下按WorkFlow与Service数组字段合并文档

MongoDB按WorkFlow和Service数组分组合并文档解决方案

需要按WorkFlow文本字段和Service数组字段(数组内元素顺序不影响分组)分组合并文档,将同组的原始文档内容整理到Assets数组中,同时合并去重Service字段。

方法一:使用MongoDB聚合管道(推荐)

利用聚合管道的阶段操作,先标准化Service数组的分组键,再完成分组和结构整理:

完整聚合代码

db.collection.aggregate([
  // 1. 标准化Service数组:提取value并排序,生成用于分组的唯一key
  {
    $addFields: {
      serviceGroupKey: {
        $sortArray: {
          input: "$Service.value",
          sortBy: 1
        }
      }
    }
  },
  // 2. 按WorkFlow和标准化后的serviceGroupKey分组
  {
    $group: {
      _id: {
        WorkFlow: "$WorkFlow",
        serviceGroupKey: "$serviceGroupKey"
      },
      // 保留第一个文档的Service作为合并后的Service(同组内结构一致)
      Service: { $first: "$Service" },
      // 收集同组的资产信息
      Assets: {
        $push: {
          _id: "$_id",
          AssetServiceClassification: "$AssetServiceClassification",
          LevelArray: "$LevelArray"
        }
      }
    }
  },
  // 3. 整理输出结构,移除临时分组key
  {
    $project: {
      _id: 0,
      WorkFlow: "$_id.WorkFlow",
      Service: 1,
      Assets: 1
    }
  }
])

代码解释

  • $addFields阶段:将Service数组中的value提取出来并排序,生成serviceGroupKey,确保元素顺序不同但内容相同的Service数组会被归为同一组。
  • $group阶段:以WorkFlow和serviceGroupKey作为分组依据,用$first保留一组中的Service结构,用$push收集所有同组的资产信息到Assets数组。
  • $project阶段:调整输出结构,去除临时的_id分组字段,整理成期望的格式。

方法二:客户端代码处理(非聚合方式)

如果不想使用聚合管道,可以在查询所有文档后,通过客户端代码完成分组逻辑,以Node.js为例:

示例代码

async function groupDocuments() {
  const docs = await db.collection.find().toArray();
  const groupMap = new Map();

  docs.forEach(doc => {
    // 生成分组键:WorkFlow + 排序后的Service value字符串
    const sortedServiceValues = doc.Service.map(s => s.value).sort().join(',');
    const groupKey = `${doc.WorkFlow}_${sortedServiceValues}`;

    if (!groupMap.has(groupKey)) {
      groupMap.set(groupKey, {
        WorkFlow: doc.WorkFlow,
        Service: doc.Service,
        Assets: []
      });
    }

    // 将当前文档的资产信息加入Assets数组
    groupMap.get(groupKey).Assets.push({
      _id: doc._id.toString(),
      AssetServiceClassification: doc.AssetServiceClassification,
      LevelArray: doc.LevelArray
    });
  });

  // 将Map转换为数组,即最终结果
  return Array.from(groupMap.values());
}

代码说明

  • 查询所有文档后,通过sort()统一Service中value的顺序,生成唯一的分组键。
  • 使用Map存储分组,键为生成的分组标识,值为目标结构的对象。
  • 遍历每个文档,将资产信息追加到对应分组的Assets数组中,最后将Map转换为数组得到结果。

输入示例

[{
  "_id": { "$oid": "62f9fd54259335683bc54ac3" },
  "WorkFlow": "Vendor",
  "Service": [
    { "value": "6235b52ea216f20e1b00ad43" },
    { "value": "6235b538a216f20e1b00ad46" }
  ],
  "AssetServiceClassification": "Business",
  "LevelArray": [
    {
      "Level": "6235b4f5a216f20e1b00ad36",
      "StaffName": "620a23bbc7e6a4378ff8ad74",
      "Designation": "61efa3a5a444008633b223dd"
    },
    {
      "Level": "6235b500a216f20e1b00ad39",
      "StaffName": "620b4d4995c3061565e63b08",
      "Designation": "61efa3aca444008633b223e0"
    }
  ]
},
{
  "_id": { "$oid": "62f9f5f9e26c8912b86c61b8" },
  "WorkFlow": "Vendor",
  "Service": [
    { "value": "6235b538a216f20e1b00ad46" },
    { "value": "6235b52ea216f20e1b00ad43" }
  ],
  "AssetServiceClassification": "Normal",
  "LevelArray": [
    {
      "Level": "6235b4f5a216f20e1b00ad36",
      "StaffName": "620a2351c7e6a4378ff8ad4c",
      "Designation": "61efa3a5a444008633b223dd"
    },
    {
      "Level": "6235b500a216f20e1b00ad39",
      "StaffName": "620a2387c7e6a4378ff8ad60",
      "Designation": "61efa3aca444008633b223e0"
    }
  ]
}]

输出示例

[{
  "WorkFlow": "Vendor",
  "Service": [
    { "value": "6235b52ea216f20e1b00ad43" },
    { "value": "6235b538a216f20e1b00ad46" }
  ],
  "Assets": [
    {
      "_id": "62f9fd54259335683bc54ac3",
      "AssetServiceClassification": "Business",
      "LevelArray": [
        {
          "Level": "6235b4f5a216f20e1b00ad36",
          "StaffName": "620a23bbc7e6a4378ff8ad74",
          "Designation": "61efa3a5a444008633b223dd"
        },
        {
          "Level": "6235b500a216f20e1b00ad39",
          "StaffName": "620b4d4995c3061565e63b08",
          "Designation": "61efa3aca444008633b223e0"
        }
      ]
    },
    {
      "_id": "62f9f5f9e26c8912b86c61b8",
      "AssetServiceClassification": "Normal",
      "LevelArray": [
        {
          "Level": "6235b4f5a216f20e1b00ad36",
          "StaffName": "620a2351c7e6a4378ff8ad4c",
          "Designation": "61efa3a5a444008633b223dd"
        },
        {
          "Level": "6235b500a216f20e1b00ad39",
          "StaffName": "620a2387c7e6a4378ff8ad60",
          "Designation": "61efa3aca444008633b223e0"
        }
      ]
    }
  ]
}]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 13:24:29