Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo Multiple Level Aggregate Group

Given the following data after unwinding in an aggregate:

let workOrders = [
    {customer: 'A', job: 'Apple', chemical: {name: 'Chem A', quantity: 500}},
    {customer: 'A', job: 'Banana', chemical: {name: 'Chem B', quantity: 400}},
    {customer: 'A', job: 'Banana', chemical: {name: 'Chem C', quantity: 300}},
    {customer: 'B', job: 'Cherry', chemical: {name: 'Chem A', quantity: 200}}
]

Output needed:

[
  {
    customer: 'A',
    jobs: [
      {
        job: 'Apple',
        chemicals: [
          {name: 'Chem A', quantity: 500}
        ]
      },
      {
        job: 'Banana',
        chemicals: [
          {name: 'Chem B', quantity: 400},
          {name: 'Chem C', quantity: 300}
        ]
      }
    ]
  },
  {
    customer: 'B',
    jobs: [
      {
        job: 'Cherry',
        chemicals: [
          {name: 'Chem A', quantity: 200}
        ]
      }
    ]
  }
]

I understand how to use group and group it by customer first, but then I don't understand how to make the nested chemicals array without messing up the initial customer group.

I tried something like this but it doesn't like the inner $push.

{ "$group": { "_id": "$customer", "groups": { $push: { "group_data": "$customer", "group_count": {$sum: "$customer"}, "group_child": { $push: { "group_data": "$job", "group_count": {$sum: "$job"}, "group_children": { $push: { "group_data": "$chemical.name", "group_count": {$sum: "$chemical.name"} } } } } } } }

Also would like to add the total of quantity per Customer and per Job

like image 356
user1779362 Avatar asked Oct 18 '25 22:10

user1779362


2 Answers

To make nested chemicals you just need two $group stages:

    db.collection.aggregate([
    {
        $group: {
            _id: { customer: "$customer", job: "$job" },
            chemicals: { $push: "$chemical" },
            jobTotal: { $sum: "$chemical.quantity" }
        }
    },
    {
        $group: {
            _id: "$_id.customer",
            jobs: { $push: { job: "$_id.job", jobTotal: "$jobTotal", chemicals: "$chemicals" } },
            customerTotal: { $sum: "$jobTotal" }
        }
    },
    {
        $project: {
            _id: 0,
            customer: "$_id.customer",
            customerTotal: 1,
            jobs: 1
        }
    }
])

Mongo Playground

like image 122
mickl Avatar answered Oct 20 '25 16:10

mickl


db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $group: {
             _id:{job:'$job'},
             chemicals:{$push:'$chemical'},
             docObj:{$first:'$$CURRENT'}

            }
        },

        // Stage 2
        {
            $group: {
                _id:{customer:'$docObj.customer'},
                jobs:{$push:{job:'$_id.job',chemicals:'$chemicals'}}

            }
        },

        // Stage 3
        {
            $project: {
               customer:'$_id.customer',
               jobs:1,
               _id:0
            }
        },

    ]



);
like image 43
Rubin Porwal Avatar answered Oct 20 '25 16:10

Rubin Porwal