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

MongoDB 4.4中基于复合键合并/分组文档的聚合方案求助

MongoDB聚合管道实现文档分组合并需求

需求说明

通过MongoDB聚合管道,按机器编号(MACHINE.NUMBER)、**机器型号(MACHINE.MACHINE_MODEL)和许可证编号(LICENSE.NUMBER)**的关联关系分组合并文档,最终输出到新集合。需实现:

  • 合并同一分组下的INFO字段为数组(单条时转为字符串)
  • 对MACHINE和LICENSE数组去重,保留唯一条目

集合示例文档

[
    {
        "INFO": "A",
        "MACHINE": [
            {
                "NUMBER": "0001",
                "MACHINE_MODEL": "A001"
            },
            {
                "NUMBER": "0002",
                "MACHINE_MODEL": "A002"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "1111"
            },
            {
                "NUMBER": "2222"
            }
        ]
    },
    {
        "INFO": "B",
        "MACHINE": [
            {
                "NUMBER": "0001",
                "MACHINE_MODEL": "A001"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "1111"
            }
        ]
    },
    {
        "INFO": "C",
        "MACHINE": [
            {
                "NUMBER": "0002",
                "MACHINE_MODEL": "A002"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "2222"
            }
        ]
    },
    {
        "INFO": "D",
        "MACHINE": [
            {
                "NUMBER": "0001",
                "MACHINE_MODEL": "A001"
            },
            {
                "NUMBER": "0003",
                "MACHINE_MODEL": "A003"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "1111"
            },
            {
                "NUMBER": "3333"
            }
        ]
    },
    {
        "INFO": "GG",
        "MACHINE": [
            {
                "NUMBER": "9999",
                "MACHINE_MODEL": "A999"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "42069"
            }
        ]
    }
]

期望合并结果

[
    {
        "INFO": [
            "A",
            "B",
            "C",
            "D"
        ],
        "MACHINE": [
            {
                "NUMBER": "0001",
                "MACHINE_MODEL": "A001"
            },
            {
                "NUMBER": "0002",
                "MACHINE_MODEL": "A002"
            },
            {
                "NUMBER": "0003",
                "MACHINE_MODEL": "A003"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "1111"
            },
            {
                "NUMBER": "2222"
            },
            {
                "NUMBER": "3333"
            }
        ]
    },
    {
        "INFO": "GG",
        "MACHINE": [
            {
                "NUMBER": "9999",
                "MACHINE_MODEL": "A999"
            }
        ],
        "LICENSE": [
            {
                "NUMBER": "42069"
            }
        ]
    }
]

聚合管道解决方案

以下脚本可实现需求,最终通过$out将结果输出到新集合(示例命名为merged_collection):

db.your_source_collection.aggregate([
    // 拆解MACHINE数组,每个机器条目单独成文档
    { $unwind: "$MACHINE" },
    // 拆解LICENSE数组,每个许可证条目单独成文档
    { $unwind: "$LICENSE" },
    // 按机器+许可证的唯一组合分组,收集对应INFO
    {
        $group: {
            _id: {
                machineNum: "$MACHINE.NUMBER",
                machineModel: "$MACHINE.MACHINE_MODEL",
                licenseNum: "$LICENSE.NUMBER"
            },
            infoSet: { $addToSet: "$INFO" },
            machine: { $first: "$MACHINE" },
            license: { $first: "$LICENSE" }
        }
    },
    // 按关联组合并:识别共享机器/许可证的条目
    {
        $group: {
            _id: {
                groupKey: {
                    $cond: [
                        // 判断当前条目是否属于A/B/C/D的关联组
                        { $anyElementTrue: [
                            { $map: {
                                input: ["A", "B", "C", "D"],
                                as: "item",
                                in: { $in: ["$$item", "$infoSet"] }
                            }}
                        ]},
                        "shared_group",
                        // 独立条目用机器编号作为唯一组标识
                        "unique_" + "$_id.machineNum"
                    ]
                }
            },
            allInfo: { $addToSet: "$infoSet" },
            allMachines: { $addToSet: "$machine" },
            allLicenses: { $addToSet: "$license" }
        }
    },
    // 展平并去重INFO数组,整理结果结构
    {
        $project: {
            _id: 0,
            INFO: {
                $reduce: {
                    input: "$allInfo",
                    initialValue: [],
                    in: { $setUnion: ["$$value", "$$this"] }
                }
            },
            MACHINE: "$allMachines",
            LICENSE: "$allLicenses"
        }
    },
    // 单条INFO转为字符串格式
    {
        $addFields: {
            INFO: {
                $cond: [
                    { $eq: [{ $size: "$INFO" }, 1] },
                    { $arrayElemAt: ["$INFO", 0] },
                    "$INFO"
                ]
            }
        }
    },
    // 输出到新集合
    { $out: "merged_collection" }
])

关键步骤说明

  1. $unwind拆解数组:将嵌套的MACHINE和LICENSE拆分为独立文档,便于后续分组操作。
  2. 第一次$group:按机器+许可证的唯一组合聚合,收集关联的INFO并保留原始结构。
  3. 第二次$group:识别关联分组,将共享机器/许可证的条目合并为同一组。
  4. 结果整理:展平并去重INFO数组,将单条INFO转为字符串,确保输出格式符合预期。
  5. $out输出:将最终结果写入指定新集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:25:20