MongoDB-将嵌入式文档中的行解压缩到自己的列中

时间:2019-11-15 07:01:32

标签: mongodb nosql mongodb-query aggregation-framework nosql-aggregation

问题

所以我有一个看起来像这样的MongoDB文档:

Awards


    [
      {
        "year": "2017",
        "winners": [
          {
            "name": "james",
            "id": 1
          },
          {
            "name": "adam",
            "id": 2
          }
        ]
      },
      {
        "year": "2018",
        "winners": [
          {
            "name": "mary",
            "id": 3
          },
          {
            "name": "jane",
            "id": 4
          }
        ]
      }
    ]

我基本上是在尝试每年扩大赢家,以便使模式大致为(year, winner_id),我以后可以将其用于计划的联接。像这样:

[
   {
     "year":"2017",
     "winner_id":1
   },   
   {
     "year":"2017",
     "winner_id":2
   }, 
   {
     "year":"2018",
     "winner_id":3
   },
   {
     "year":"2018",
     "winner_id":4
   }
]

我尝试过的东西

从直觉上讲,我正在寻找类似$unwind的东西,但是问题是winners不是数组。

  • 我尝试了db.awards.aggregate({'$unwind':'$winners.id'}),但是没有用。 (结果为空)

  • 所以后来我想到了db.awards.aggregate({'$unwind': {'$objectToArray':'$winners.id'}}),但是那也不起作用。 (出现错误)

  • 根据this post,我应该这样做:

db.awards.aggregate(
 { '$project': {
    _id: 1,
    'winners': 1
  } },
{'$unwind': '$winners'},
{'$unwind': '$winners.id'}
)

但是,即使那样行不通,我仍然获得每个winner

的嵌入式文档

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您需要先$unwind winners并使用$replaceRoot使其位于根位置

db.collection.aggregate([
  { "$unwind": "$winners" },
  { "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$winners",
          { "year": "$year" }
        ]
      }
    }
  }
])

MongoPlayground

答案 1 :(得分:1)

您的数据是无效的JSON。假设winners属性很可能是数组。

在您的聚合命令中,我可以看到另外三个问题:

  1. 您还应该将聚合管道作为数组传递给aggregate函数。
  2. $project的语法在聚合管道中有所不同。您没有定义应包括哪些字段。您确实定义了实际的映射
  3. 我不明白您为什么要取消获奖者ID。 unwind的属性应该是一个数组,在您的示例中,只有winners数组。

我认为在投影前先做$unwind

db.awards.aggregate(
  [
    {
      $unwind: { path: '$winners' }
    },
    {
      $project: {
        year: '$year',
        winner_id: '$winners.id'
      }
    }
  ]
);

Mongo Playground