MongoDB:在深层嵌套的对象数组中聚合查找

时间:2020-10-02 19:20:59

标签: mongodb mongodb-query aggregation-framework

我有两个收藏夹:

音频

[
       {
        "_id": "5f6b1a2e69eef14818ca03a7",
        "audioURL": "https://boyd.org",
        "state": "draft",
       }
       {
        "_id": "5f6b1e1c6297f34bc6f1fee3",
        "name": "navigate",
        "audioURL": "http://mariane.org",
        "state": "draft",
       },
       {
        "_id": "5f5b5423ba39f738d593b504",
        "audioURL": "https://storage/test123mp31599820832928.mp3",
        "state": "draft",
       }
]

课程:

 "lessons": [
  {
   "_id": "5f770e275cef7a611f3cf931",
   "minigameDescriptions": [
    {
     "assessmentSections": [
      {
       "mark": "step_1",
       "start": 1,
       "end": 2,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
        "previewTrackAudioId": "5f6b1a2e69eef14818ca03a7"
       }
      },
      {
       "mark": "step_2",
       "start": 3,
       "end": 6,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1e1c6297f34bc6f1fee3",
        "previewTrackAudioId": "5f6b1e1c6297f34bc6f1fee3"
       }
      },
      {
       "mark": "step_3",
       "start": 7,
       "end": 10,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
        "previewTrackAudioId": "5f5b5423ba39f738d593b504"
       }
      }
     ],
     "drumStyleName": "DrumStyleHalftimeShuffle",
     "onboarding": false,
     "showHints": false,
     "minigameType": "StrummingTrainer",
    }
   ],
   "_updated_at": "2020-10-02T12:00:23.848Z",
  }
 ]
}

现在我必须汇总一下,因为在每个mingameDescriptions.assessmentSections中都有一个属性stepAudio,它具有previewTrackAudioIdbackingTrackAudioId。这些对集合“音频”的引用,我需要将它们作为对象加入那里(音频主键为_id)。我尝试遵循管道(现在我仅尝试查找previewTrackAudio):

{
        $unwind: {
          path: "$minigameDescriptions.assessmentSections",
          preserveNullAndEmptyArrays: true
        },
      },
      {
        $lookup: {
          from: "audios",
          let: {
            audioId: "$minigameDescriptions.assessmentSections.stepAudio.previewTrackAudioId"
          },
          pipeline: [
            {
              $match: {
                $expr: {
                  $eq: ["$_id", "$$audioId"]
                }
              }
            }
          ],
          as: "minigameDescriptions.assessmentSections.stepAudio.previewTrackAudio"
        }
      },
      {
        $unwind: {
          preserveNullAndEmptyArrays: true,
          path: "$minigameDescriptions.assessmentSections.stepAudio.previewTrackAudio"
        }
      }

“ kinda”有效,我得到以下结果:

{
 "lessons": [
  {
   "_id": "5f770e275cef7a611f3cf931",
   "minigameDescriptions": [
    {
     "assessmentSections": {
      "mark": "step_2",
      "start": 3,
      "end": 6,
      "stepAudio": {
       "backingTrackAudioId": "5f6b1e1c6297f34bc6f1fee3",
       "previewTrackAudioId": "5f6b1e1c6297f34bc6f1fee3",
       "previewTrackAudio": {
        "_id": "5f6b1e1c6297f34bc6f1fee3",
        "name": "navigate",
        "audioURL": "http://mariane.org",
        "state": "draft",
       }
      }
     },
     "drumStyleName": "DrumStyleHalftimeShuffle",
     "onboarding": false,
     "showHints": false,
     "minigameType": "StrummingTrainer",
    },
    {
     "assessmentSections": {
      "mark": "step_3",
      "start": 7,
      "end": 10,
      "stepAudio": {
       "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
       "previewTrackAudioId": "5f5b5423ba39f738d593b504",
       "previewTrackAudio": {
        "_id": "5f5b5423ba39f738d593b504",
        "audioURL": "https://storage/test123mp31599820832928.mp3",
        "state": "draft",
       }
      }
     },
     "drumStyleName": "DrumStyleHalftimeShuffle",
     "onboarding": false,
     "showHints": false,
     "minigameType": "StrummingTrainer",
    },
    {
     "assessmentSections": {
      "mark": "step_1",
      "start": 1,
      "end": 2,
      "stepAudio": {
       "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
       "previewTrackAudioId": "5f6b1a2e69eef14818ca03a7",
       "previewTrackAudio": {
        "_id": "5f6b1a2e69eef14818ca03a7",
        "audioURL": "https://boyd.org",
        "state": "draft",
       }
      }
     },
     "drumStyleName": "DrumStyleHalftimeShuffle",
     "onboarding": false,
     "showHints": false,
     "minigameType": "StrummingTrainer",
    }
   ],
   "_updated_at": "2020-10-02T12:00:23.848Z",
  }
 ]
}

但是现在,我有了一个包含三个对象的数组,它们具有mingameDescriptions.assessmentSections以及来自assesmentSections的重复属性,而不是包含3个minigameDescriptions的数组,这是错误的:/。我该如何解决?

我想得到的是:

 "lessons": [
  {
   "_id": "5f770e275cef7a611f3cf931",
   "minigameDescriptions": [
    {
     "assessmentSections": [
      {
       "mark": "step_1",
       "start": 1,
       "end": 2,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
        "previewTrackAudioId": "5f6b1a2e69eef14818ca03a7",
        "previewTrackAudio": {
         "_id": "5f6b1a2e69eef14818ca03a7",
         "audioURL": "https://boyd.org",
         "state": "draft",
        }
       }
      },
      {
       "mark": "step_2",
       "start": 3,
       "end": 6,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1e1c6297f34bc6f1fee3",
        "previewTrackAudioId": "5f6b1e1c6297f34bc6f1fee3",
        "previewTrackAudio": {
          "_id": "5f5b5423ba39f738d593b504",
          "audioURL": "https://storage/test123mp31599820832928.mp3",
          "state": "draft",
         }
       }
      },
      {
       "mark": "step_3",
       "start": 7,
       "end": 10,
       "stepAudio": {
        "backingTrackAudioId": "5f6b1a2e69eef14818ca03a7",
        "previewTrackAudioId": "5f5b5423ba39f738d593b504",
        "previewTrackAudio": {
         "_id": "5f5b5423ba39f738d593b504",
         "audioURL": "https://storage/test123mp31599820832928.mp3",
         "state": "draft",
        }
       }
      }
     ],
     "drumStyleName": "DrumStyleHalftimeShuffle",
     "onboarding": false,
     "showHints": false,
     "minigameType": "StrummingTrainer",
    }
   ],
   "_updated_at": "2020-10-02T12:00:23.848Z",
  }
 ]
}

1 个答案:

答案 0 :(得分:1)

您尝试的是正确的。

[
  {
    $unwind: "$minigameDescriptions"
  },
  {
    $unwind: "$minigameDescriptions.assessmentSections"
  },
  {
    $lookup: {
      from: "Audios",
      let: {
        audioId: "$minigameDescriptions.assessmentSections.stepAudio.previewTrackAudioId"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$_id",
                "$$audioId"
              ]
            }
          }
        }
      ],
      as: "minigameDescriptions.assessmentSections.stepAudio.previewTrackAudio"
    }
  },
      {
    $group: {
      _id: {
        _id: "$_id",
        /**   assId: "$minigameDescriptions.assessmentSections.mark"*/
        
      },
      assessmentSections: {
        $addToSet: "$minigameDescriptions.assessmentSections"
      },
      drumStyleName: {
        $first: "$minigameDescriptions.drumStyleName"
      },
      minigameType: {
        $first: "$minigameDescriptions.minigameType"
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      minigameDescriptions: {
        $addToSet: {
          assessmentSections: "$assessmentSections",
          drumStyleName: "$drumStyleName",
          minigameType: "$minigameType"
        }
      }
    }
  }
]

工作Mongo playground

注意:这里我们完成了两个展开,因此最好执行分组操作。 Carefule,我已经评论了第一组中的assessmentId,该注释在您的文档中不存在。但最好能在assessmentSections中标识每个元素,这有助于避免复杂化