2

I have the following document structure (it is a small LMS):

[
  {
    "name": "course1",
    "code": "C1",
    "levels": [
      {
        "levelname": "level01",
        "order": 1,
        "modules": [
          {
            "modulename": "title module 01",
            "code": "MC1_01",
            "order": 1,
            "title": "module title 01"
          },
          {
            "modulename": "title module 02",
            "code": "MC1_02",
            "order": 2,
            "title": "module title 02"
          }
        ]
      },
      {
        "levelname": "level02",
        "modules": [
          {
            "modulename": "title module 11",
            "code": "MC1_11",
            "order": 1,
            "title": "module title 01"
          },
          {
            "modulename": "title module 12",
            "code": "MC1_12",
            "order": 2,
            "title": "module title 02"
          }
        ]
      }
    ]
  },
  {
    "name": "course2",
    "code": "C2",
    "levels": [
      {
        "levelname": "level01",
        "order": 1,
        "modules": [
          {
            "modulename": "title module 01",
            "code": "MC2_01",
            "order": 1,
            "title": "module title 01"
          },
          {
            "modulename": "title module 02",
            "code": "MC2_02",
            "order": 2,
            "title": "module title 02"
          }
        ]
      },
      {
        "levelname": "level02",
        "modules": [
          {
            "modulename": "title module 10",
            "code": "MC2_10",
            "order": 1,
            "title": "module title 01"
          },
          {
            "modulename": "title module 11",
            "code": "MC2_11",
            "order": 2,
            "title": "module title 02"
          }
        ]
      }
    ]
  }
]

In short words I have a document with all courses, a single course consists of several levels and in each level there are many modules: COURSE > LEVELS > MODULES

(HERE'S A READY PLAYGROUND: https://mongoplayground.net/p/Yo3OJQEQxf5 )

Knowing the code or the _id, I have to extract a single mode but I also have to keep the structure of the document unchanged and also keep the properties of the parent documents. My expected output is (when I look for module with code MC1_02):

{
    "name": "course1",
    "code": "C1",
    "levels": [
        {
            "levelname": "level01",
            "order": 1,
            "modules": [
                {
                    "modulename": "title module 02",
                    "code": "MC1_02",
                    "order": 2,
                    "title": "module title 02"
                }
            ]
        }
    ]
}

I am trying several attempts and have already tried using the solutions highlighted in these answers:

Mongo db Query to filter nested array of objects in document
MongoDB nested array search using $map
$filter upto 3 nested level in mongodb

I know exactly how to do it using $unwind and $group, but for me it's not the best solution, I prefer to use $map and $filter. At the same time, I can't use $project or any other aggregation operator that force me to enumerate all properties one by one, because in any level there are a great number of different properties and I can't list them, I simply need to keep all.

A thousand thanks to those who will help me :)

crivella
  • 514
  • 5
  • 19

1 Answers1

0
  • $match to match code condition
  • $map to iterate loop of levels array
  • $filter to iterate loop of modules array and filter modules that have code: "MC1_02"
  • $mergeObjects to merge current object with updated modules field
  • $filter above result if modules is not empty []
db.collection.aggregate([
  { $match: { "levels.modules.code": "MC1_02" } },
  {
    $addFields: {
      levels: {
        $filter: {
          input: {
            $map: {
              input: "$levels",
              in: {
                $mergeObjects: [
                  "$$this",
                  {
                    modules: {
                      $filter: {
                        input: "$$this.modules",
                        cond: { $eq: ["$$this.code", "MC1_02"] }
                      }
                    }
                  }
                ]
              }
            }
          },
          cond: { $ne: ["$$this.modules", []] }
        }
      }
    }
  }
])

Playground

turivishal
  • 34,368
  • 7
  • 36
  • 59