MongoDB聚合:将每个数组值从另一个字段添加到数组内的每个对象。合并/合并来自不同字段的两个数组

时间:2020-04-13 10:28:11

标签: mongodb mongoose aggregation-framework

我正处于复杂的聚合查询(具有查找和许多组/展开阶段)的中间,并且遇到了组合来自不同字段的两个不同数组的问题。

目前,在其中一个阶段之后(在我的大查询的中间或查找之后),我得到以下输出:

{
  _id: 1,
  quantity: [2, 1, 3]
  reagents: [ 
     {name: "FirstItem", other_field: ... },
     {name: "SecondItem", other_field: ... },
     {name: "ThirdItem", other_field: ... }
  ]
}

我想要:

  _id: 1,
  reagents: [ 
     {name: "FirstItem", quantity: 2 },
     {name: "SecondItem", quantity: 1 },
     {name: "ThirdItem", quantity: 3 }
  ]

因此,我想根据其索引将每个[quantity]值添加到[reagents]内的每个对象作为字段,就像{object}内的第一个reagents应该有第一个{{1 }}来自element

具有数组索引的架构):

[quantity]

问题:

我无法在汇总之后或之前这样做,因为:

  • 我没有必要的数据,因为这是从不同集合中查找的结果。

  • 之后我将无法执行此操作,因为在此之后,我应该通过另一个字段quantity: [2, 1, 3, ... n] ↓ ↓ ↓ ↓ reagents: [1, 2, 3, ... n] 来处理数据,因此$group的排序顺序已经丢失并且无法恢复。

    li>

UPD 我知道我可以(可能应该将[reagents]阶段用于$unwind,但是我没有找到any relevant Aggregation Stage Operators in Mongo Manual。如果您知道必要的,请指出。

2 个答案:

答案 0 :(得分:2)

您可以在舞台下方添加

 { "$addFields": {
   "reagents": {
     "$map": {
       "input": { "$range": [0, { "$size": "$reagents" }] },
       "in": {
         "name": {
           "$arrayElemAt": ["$reagents.name", "$$this"]
         },
         "quantity": {
           "$arrayElemAt": ["$quantity", "$$this"]
         }
       }
     }
   }
 }}

MongoPlayground

答案 1 :(得分:2)

如果您不需要在结果中保留名称和数量以外的其他字段,

@Ashh的答案将非常有效(并且afaik是最佳解决方案)。 但是,如果必须保留它们,则必须手动添加每个字段,这有时可能很乏味。 还有另一种“通用”解决方案可以解决这种情况,该$zip运算符旨在按索引合并数组。

db.collection.aggregate([
  {
    $addFields: {
      reagents: {
        $map: {
          input: {
            $zip: {
              inputs: [
                "$quantity",
                "$reagents"
              ]
            }
          },
          as: "reagent",
          in: {
            $mergeObjects: [
              {
                $arrayElemAt: [
                  "$$reagent",
                  1
                ]
              },
              {
                quantity: {
                  $arrayElemAt: [
                    "$$reagent",
                    0
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
])

Mongo playground