MongoDB: агрегированный поиск в глубоко вложенном массиве объектов

#mongodb #mongodb-query #aggregation-framework

#mongodb #mongodb-запрос #агрегация-фреймворк

Вопрос:

У меня есть две коллекции:

Аудиозаписи

 [
       {
        "_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 , которое имеет previewTrackAudioId и backingTrackAudioId . Это ссылки на коллекцию «аудио», и мне нужно объединить их там в качестве объектов (есть первичный ключ _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"
        }
      }
  

And it «kinda» works, I get following result:

 {
 "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",
  }
 ]
}
  

Но теперь вместо массива с 3 mingameDescriptions.assessmentSections у меня есть массив с тремя объектами, которые имеют assesmentSections наряду с повторяющимися свойствами, из 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. Вам необходимо опубликовать обе коллекции. И не размещайте ненужные поля, которые создают неудобства для других при просмотре

2. Правильно, я опубликовал обе коллекции и удалил ненужные поля.

Ответ №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

Примечание: здесь мы выполнили два развертывания, поэтому лучше выполнить групповую операцию. Осторожно, я прокомментировал assessmentId первую группу, которой нет в вашем документе. Но лучше, если есть что-нибудь для идентификации каждого элемента, в assessmentSections котором помогает не усложнять

Комментарии:

1. Это почти то, что мне нужно, спасибо! Я отредактировал сообщение, чтобы добавить, какой ответ мне нужен, поскольку в вашем решении я получаю только assessmentSections , а остальные свойства minigameDescriptions отсутствуют. Можете ли вы помочь мне с этим?

2. Я обновил свой ответ, который я сделал для нескольких полей, вы можете следовать тем же путем

3. Это вам помогает?

4. Я проверю это позже и дам вам знать!