简体   繁体   中英

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"
            ]
          }
        ]
      }
    ]
  }
]

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM