Mongodb grouping array of child

Viewed 126

Good day! I am studying mongodb and I find it difficult to group a child array. I want to group the parameters with same id.

Is it possible in mongodb to group array of child?

Initial array of objects.

"attributes": [
    {
        "_id": "5f3553c483477525987a6852",
        "parameters": {
            "_id": "5f3553c483477525987a6853",
            "parameter": {
                "_id": "5f35539e83477525987a684e",
                "parameter": "HOMEROOM"
            },
            "percentage_allocation": 20
        }
    },
    {
        "_id": "5f3553c483477525987a6852",
        "parameters": {
            "_id": "5f35578d786afe026451470c",
            "parameter": {
                "_id": "5f3553a783477525987a684f",
                "parameter": "PERFORMANCE"
            },
            "percentage_allocation": 20
        }
    }
]

Desired Results:

"attributes": [
    {
        "_id": "5f3553c483477525987a6852",
        "parameters": [{
            "_id": "5f3553c483477525987a6853",
            "parameter": {
                "_id": "5f35539e83477525987a684e",
                "parameter": "HOMEROOM"
            },
            "percentage_allocation": 20
        },
        {
                "_id": "5f3553a783477525987a684f",
                "parameter": "PERFORMANCE"
            },
            "percentage_allocation": 20
        }]
    }
]
2 Answers

You can $unwind to flat the array. Then $group it by _id to regroup as you need. Again $group it to add to attributes array.

[
  {
    $unwind: "$attributes"
  },
  {
    $group: {
      _id: "$attributes._id",
      parameters: {
        $push: {
          _id: "$attributes._id",
          parameter: "$attributes.parameter",
          percentage_allocation: "$attributes.percentage_allocation"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      attributes: {
        $push: "$$ROOT"
      }
    }
  }
]

Working Mongo playground

Found a better solution on my nested array of objects. I used populate and it worked as I want the program to be executed. And it is much cleaner code than before.

 data = await SubjectDetails.find(query)
        .populate({
            path: 'academic_year'
        })
        .populate({
            path: 'grade_level'
        })
        .populate({
            path: 'subject'
        })
        .populate({
            path: 'attributes.attribute',
        })
        .populate({
            path: 'attributes.parameters.parameter',
        })
        .sort({
            "subject.subject": 1
        })
        .exec()
        .catch(err => {
            res.status(500).send(err);
        });
Related