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 :)

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.