如何在 MongoDB 聚合管道中将对象数组转换为嵌套对象

How to convert array of objects into nested object in MongoDB aggregation pipeline

我目前正在做一个项目,我的数据库管理系统是 MongoDB。我正在编写一个聚合管道,其中有几个阶段。我目前正在努力获得以下输出的特定阶段。 MongoDB 有太多的运算符表达式,我不知道该用哪个来实现这个。 我有一个名为 Styles 和 Skus 的集合,如下所示:

// Schema for styles
const styles = mongoose.Schema({
  id: Number,
  productId: Number,
  name: String,
  sale_price: String,
  original_price: String,
  default_price: Boolean,
}, {
  strict: false,
});

// Schema for skus
const skus = mongoose.Schema({
  id: Number,
  styleId: Number,
  size: String,
  quantity: String,
}, {
  strict: false,
});

每个款式可以有多个SKU,一对多关系。在我的聚合管道中,我使用 $lookup 来查找该特定样式的所有 SKU,并在样式文档中添加一个名为 SKU 的新字段。在 $lookup.

之后我得到了这样的结果
{
            "style_id": 1,
            "name": "Forest Green & Black",
            "original_price": "140",
            "sale_price": "0",
            "default?": true,
             "skus": [
                { 
                   "id": 37,
                   "styleId": 1,
                   "size": "XS",
                   "quantity": 16 
                },
                { 
                   "id": 38,
                   "styleId": 1,
                   "size": "S",
                   "quantity": 8
                } 
              ]  

}

预期 $lookup returns 匹配数组。但我希望我的样式文档看起来像这样。

{
            "style_id": 1,
            "name": "Forest Green & Black",
            "original_price": "140",
            "sale_price": "0",
            "default?": true,
             "skus": {
                  "37": {
                    "styleId": 1,
                   "size": "XS",
                   "quantity": 16 
                  },
                  "38": {
                   "styleId": 1,
                   "size": "S",
                   "quantity": 8
                  }
               }
                    

}

有人可以告诉我如何在聚合管道中构造上述数据吗?任何帮助将不胜感激。提前致谢。

您可以使用 $map$reduce 将数组中的对象转换为

形式
[
 {
  k: <key1>
  v: <value1>
 },
 {
  k: <key2>
  v: <value2>
 }
]

然后使用 $arrayToObject 将数组转换为对象,如:

{ 
    <key1>: <value1>,
    <key2>: <value2> 
}

加在一起,这可能看起来像:

{$addFields: {
    skus: {
      $arrayToObject: {
        $map: {
          input: "$skus",
          in: {
            k: {$toString: "$$this.id"},
            v: "$$this"
          }
        }
      }
    }
}}

Playground