在 mongo 中将两个文档合并为一个

问题描述 投票:0回答:1

我正在研究一些聚合管道。 我的上一步以以下两个文档结束:

{ x: 1, y: 60, z: 111}

{ x: 1, y: 90, z: 222}

我使用

x
作为
id
并希望将两个文档合并为:

{ x: 1, y1: { z: 111 }, y2: { z: 222} }

如有任何帮助,我们将不胜感激

我一直在尝试通过

"$group"
值来
x
它们,但最后仍然有数组;在
"$unwind"
步骤之后,又回到两个文档。

mongodb aggregation-framework
1个回答
0
投票

尽管我相信使用

$group
来保持
y
z
是最好的,但我提交此解决方案作为如何使用
$reduce
作为
for
循环以及
$arraytoObject 的力量的示例
在管道中动态构造 lval(字段)。

c=db.foo.aggregate([
    // Only need value of z for later operations:
    {$group: {_id: "$x", X: {$push: {z:"$z"}}}}

    // Iterate over X and dynamically build k-v pairs for the
    // upcoming arrayToObject.  For efficiency, in the same stage
    // ($project) we will use $getField to extact newX and leave us with just
    // the reformed array, leaving out the stateful loop bits.
    // Note we $project input X over existing X because there is no point
    // in carrying the original array through the pipeline:
    ,{$project: {X: {$getField:{input: {$reduce: {
    input: '$X',

    initialValue: {
        n:0,  // counter state
        newX:[]  // the desired target data
    },
        in: {$let: {
        vars: {qq:{$add:['$$value.n',1]}}, // n = n + 1
        in: {
            n: '$$qq', // must carry over count in the loop!

            // This is the juice.  Append to the array using
            // $concatArrays.  Note the dynamic construction
            // of the field name k (for example, it will
            // become 'y1', 'y2, etc.   Note also v is set
            // to a NEW object containing z as a field.
            newX: {$concatArrays: [
            '$$value.newX',
            [ {'k':{$concat:['y',{$toString:'$$qq'}]},
               'v':{z:'$$this.z'}
              }
            ] ]}
        }
        }}
    }}, field:'newX'}}
        }}

    /*
      All data is now set up.  To get a sense of what is happening,
      comment out this last stage and look at the "before" output.
      Astute observers will note that the pipeline stage above that
      projects X could be eliminated and the contents used directly here:

        {$replaceRoot: {newRoot: {$mergeObjects: [
        {x: '$_id'},
        {$arrayToObject: {$getField:{input: {$reduce: { ...

      This eliminates a stage for efficiency but perhaps reduces clarity.
    */
    ,{$replaceRoot: {newRoot: {$mergeObjects: [
    {x: '$_id'},
    {$arrayToObject: '$X'}
    ]}
    }}
]);
© www.soinside.com 2019 - 2024. All rights reserved.