Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unwind nested object arrays in mongodb aggregation?

I have some data with an array of objects which contains another array. I am trying to unwind the courses array then the requirements array to match subjects then group everything back together.

So far I can work fine with the courses array. But I just can't get around doing the same thing for the second array requirements.

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]

First I unwind both arrays

  {
    $unwind: {
      path: '$courses',
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $unwind: {
      path: '$courses.requirements',
      preserveNullAndEmptyArrays: true
    }
  },

How I group the first array

  {
    $group: {
      _id: '$_id',
      root: { $mergeObjects: '$$ROOT' },
      courses: { $push: '$courses' }
    }
  },
  {
    $replaceWith: {
      $mergeObjects: ['$root', '$$ROOT'],
    }
  },
  {
    $project: { root: 0 }
  },

Expected Output

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]

But I get

[
  {
    "_id": 1,
    "name": "provider name",
    "courses": [
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      },
      {
        "_id": 1,
        "name": "course name",
        "requirements": [
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          },
          {
            "subjects": [
              "SubjectA::B",
              "SubjectB::B",
              "SubjectC::B"
            ]
          }
        ]
      }
    ]
  }
]
like image 273
ABZO Avatar asked Jan 31 '26 19:01

ABZO


1 Answers

You can reconstruct tour arrays by below stages,

  • $group by _id and courses._id and get first name and course first name, and construct the requirements array
  • $group by only _id and get first name and reconstruct courses array
  {
    $group: {
      _id: {
        _id: "$_id",
        cId: "$courses._id"
      },
      name: { $first: "$name" },
      course_name: { $first: "$courses.name" },
      requirements: { $push: "$courses.requirements" }
    }
  },
  {
    $group: {
      _id: "$_id._id",
      name: { $first: "$name" },
      courses: {
        $push: {
          _id: "$_id.cId",
          name: "$course_name",
          requirements: "$requirements"
        }
      }
    }
  }

Playground

like image 53
turivishal Avatar answered Feb 03 '26 09:02

turivishal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!