MongoDB - $ ricerca in un array annidato complesso

Sep 23 2020

Sto costruendo un nuovo LMS in mongodb e ho le seguenti raccolte:

Corsi

{
  "_id": ObjectId("5f6a6b159de1304fb885b194"),
  "title": "Course test",
  "sections": [
    {
      "_id": ObjectId("5f6a6b159de1304fb885b195"),
      "title": "Section 1 - introduction",
      "order": 1,
      "modules": [
        {
          "_id": ObjectId("5f6a6b159de1304fb885b196"),
          "module_FK_id": ObjectId("5f6a6b149de1304fb885b135"),
          "title": "Module 1",
          "order": 1
        },
        {
          "_id": ObjectId("5f6a6b159de1304fb885b198"),
          "module_FK_id": ObjectId("5f6a6b149de1304fb885b14a"),
          "title": "Module 2",
          "order": 2
        },      
      ]
    },
    {
      "_id": ObjectId("5f6a6b149de1304fb885b175"),
      "title": "Section 2 - How to do something",
      "order": 2,
      "modules": [
        {
          "_id": ObjectId("5f6a6b149de1304fb885b141"),
          "module_FK_id": ObjectId("5f6a6b149de1304fb885b150"),
          "title": "Module 1",
          "order": 1
        },
        {
          "_id": ObjectId("5f6a6b149de1304fb885b15f"),
          "module_FK_id": ObjectId("5f6a6b149de1304fb885b18e"),
          "title": "Module 2",
          "order": 2
        },      
      ]
    },
  ]
}

Moduli (solo uno come esempio)

{
  "_id": ObjectId("5f6a6b149de1304fb885b135"),
  "text": "Lorem ipsum...",
  "mediaUrl": "urllinkhere"
}

Come mostrato, scelgo di avere documenti incorporati per sezioni e titoli di moduli, ma ho bisogno anche di una seconda raccolta, moduli, perché ogni modulo contiene una grande quantità di testo e il mio documento di corso potrebbe diventare troppo grande rapidamente.

Ora ho bisogno di ricostruire l'intero documento come se fosse completamente incorporato. Ecco un esempio:

   {
      "_id": ObjectId("5f6a6b159de1304fb885b194"),
      "title": "Course test",
      "sections": [
        {
          "_id": ObjectId("5f6a6b159de1304fb885b195"),
          "title": "Section 1 - introduction",
          "order": 1,
          "modules": [
            {
              "_id": ObjectId("5f6a6b159de1304fb885b196"),
              "module_FK_id": ObjectId("5f6a6b149de1304fb885b135"),
              "title": "Module 1",
              "order": 1
              "text": "Lorem ipsum...",
              "mediaUrl": "urllinkhere"
            },
            // last two fields from collection "modules"

Sto provando una combinazione diversa di aggregazione e ricerche ma non riesco a ottenere il risultato desiderato.

Qualcuno può aiutarmi?

Risposte

1 namarsood Sep 24 2020 at 13:17

Puoi costruire la pipeline di aggregazione come questa di seguito, just remember to $ group in the reverse order of $ rilassarsi operations

db.courses.aggregate([
  {
    $unwind: "$sections"
  },
  {
    $unwind: "$sections.modules"
  },
  {
    "$lookup": { "from": "modules", "localField": "sections.modules.module_FK_id", "foreignField": "_id", "as": "module_details" } }, { $unwind: {
      path: "$module_details", preserveNullAndEmptyArrays: true } }, { "$project": {
      title: 1,
      sections: {
        _id: "$sections._id", modules: { _id: "$sections.modules._id",
          module_FK_id: "$sections.modules.module_FK_id", order: "$sections.modules.order",
          title: "$sections.modules.title", mediaUrl: "$module_details.mediaUrl",
          text: "$module_details.text" }, order: "$sections.order",
        title: "$sections.title" } } }, { "$group": {
      "_id": "$sections._id", main_id: { $first: "$_id" }, main_title: { $first: "$title" }, order: { $first: "$sections.order" }, title: { $first: "$sections.title" }, modules: { $push: "$sections.modules" } } }, { "$project": {
      "_id": "$main_id", "title": "$main_title",
      section: {
        _id: "$_id", modules: "$modules",
        title: "$title", order: "$order",
        
      }
    }
  },
  {
    $group: { _id: "$_id",
      title: {
        $first: "$title"
      },
      sections: {
        $push: "$section"
      }
    }
  }
])

Esempio di lavoro