MongoDB聚合管道:按x字段合并两个文档为指定结构
MongoDB聚合管道合并同x值文档为指定结构
你可以通过$group收集同x值的文档,再结合$map、$arrayToObject和$mergeObjects实现动态生成y1、y2这类字段的结构,具体聚合管道如下:
db.collection.aggregate([ // 按x分组,收集每个文档的z值为{z: z}结构到items数组 { $group: { _id: "$x", items: { $push: { z: "$z" } } } }, // 将数组转换为指定的键值对结构,并与x合并 { $project: { _id: 0, x: "$_id", mergedFields: { $arrayToObject: { $map: { input: "$items", as: "item", in: { k: { $concat: ["y", { $toString: { $add: [{ $indexOfArray: ["$items", "$$item"] }, 1] } }] }, v: "$$item" } } } } } }, // 合并x和mergedFields里的字段到顶层 { $replaceRoot: { newRoot: { $mergeObjects: ["$mergedFields", { x: "$x" }] } } } ])
步骤说明
- $group阶段:按
x字段分组,用$push把每个文档的z值包装成{z: z}存入items数组,将同x的所有相关数据归集到一处。 - $project阶段:通过
$map遍历items数组,为每个元素生成带序号的键名(如第一个元素对应y1,第二个对应y2),再用$arrayToObject把键值对转成对象。 - $replaceRoot阶段:用
$mergeObjects把x字段和生成的y1、y2等字段合并,替换为新的根文档,得到目标结构。
如果你的场景中同x值的文档数量固定为2,也可以用更简洁的写法:
db.collection.aggregate([ { $group: { _id: "$x", y1: { $first: { z: "$z" } }, y2: { $last: { z: "$z" } } } }, { $project: { _id: 0, x: "$_id", y1: 1, y2: 1 } } ])
这种写法效率更高,但仅适用于固定数量的文档;若同x值的文档数量不固定,优先选择第一种动态生成的方法。
内容的提问来源于stack exchange,提问作者dankosorkin
相关产品推荐
相关产品推荐

