0

I have MongoDB collection with below documents:

[
   {
      "productType":"Bike",
      "company":"yamaha",
      "model":"y1"
   },
   {
      "productType":"Bike",
      "company":"bajaj",
      "model":"b1"
   },
   {
      "productType":"Bike",
      "company":"yamaha",
      "model":"y1"
   },
   {
      "productType":"Car",
      "company":"Maruti",
      "model":"m1"
   },
   {
      "productType":"Bike",
      "company":"yamaha",
      "model":"y2"
   },
   {
      "productType":"Car",
      "company":"Suzuki",
      "model":"s1"
   }
]

I want my output to be like :

{
    "productType": [
        {
            "name": "Bike",
            "count": 4,
            "companies": [
                {
                    "name": "Yamaha",
                    "count": 3,
                    "models": [
                        {
                            "name": "y1",
                            "count": 2
                        },
                        {
                            "name": "y2",
                            "count": 1
                        }
                    ]
                },
                {
                    "name": "Bajaj",
                    "count": 1,
                    "models": [
                        {
                            "name": "b1",
                            "count": 1
                        }
                    ]
                }
            ]
        },
        {
            "name": "Car",
            "count": 2,
            "companies": [
                {
                    "name": "Maruti",
                    "count": 1,
                    "models": [
                        {
                            "name": "m1",
                            "count": 1
                        }
                    ]
                },
                {
                    "name": "Suzuki",
                    "count": 1,
                    "models": [
                        {
                            "name": "s1",
                            "count": 1
                        }
                    ]
                }
            ]
        }
    ]
}

I am not able to understand how to create arrays inside existing array using $push. I know we can create an array using $push but how to create array of array with it ? In future, I might want to add "metaData" field also along with name and count.

5
  • You need to use the Accumulator ($group) $push operator. Commented Mar 22, 2021 at 6:49
  • can you explain more ? Commented Mar 22, 2021 at 6:50
  • Is this a valid json object? Or you ave an array of objects? share valid data set. How does your collection look like? Commented Mar 22, 2021 at 7:00
  • The collection is shown in the question. Commented Mar 22, 2021 at 7:05
  • Ok got it, each object is one document ? Commented Mar 22, 2021 at 8:06

2 Answers 2

2

You have to run multiple $group stages, one for each level:

db.collection.aggregate([
   {
      $group: {
         _id: { company: "$company", productType: "$productType", model: "$model" },
         count: { $sum: 1 }
      }
   },
   {
      $group: {
         _id: { productType: "$_id.productType", company: "$_id.company" },
         models: { $push: { name: "$_id.model", count: "$count" } },
         count: { $sum: "$count" }
      }
   },
   {
      $group: {
         _id: "$_id.productType",
         companies: { $push: { company: "$_id.company", models: "$models", count: "$count" } },
         count: { $sum: "$count" }
      }
   },
   { $set: { name: "$_id", _id: "$$REMOVE" } },
   {
      $group: {
         _id: null,
         productType: { $push: "$$ROOT" }
      }
   }
])

Mongo Playground

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

2 Comments

Thank You. Can you explain the thought process how you formed this query ?
You have to start from leaf sub-document (models: [...]) and then go step by step up to the root level. (productType: ...). Start the aggregation with the first stage and have a look at the result. Then add the next stage and have again a look at the result. Continue with each stage one by one.
1

Try this:

db.testCollection.aggregate([
    {
        $group: {
            _id: {
                name: "$productType",
                company: "$company",
                model: "$model"
            },
            count: { $sum: 1 }
        }
    },
    {
        $group: {
            _id: {
                name: "$_id.name",
                company: "$_id.company"
            },
            count: { $sum: "$count" },
            models: {
                $push: {
                    name: "$_id.model",
                    count: "$count"
                }
            }
        }
    },
    {
        $group: {
            _id: { name: "$_id.name" },
            count: { $sum: "$count" },
            companies: {
                $push: {
                    name: "$_id.company",
                    count: "$count",
                    models: "$models"
                }
            }
        }
    },
    {
        $group: {
            _id: null,
            productType: {
                $push: {
                    name: "$_id.name",
                    count: "$count",
                    companies: "$companies"
                }
            }
        }
    },
    {
        $project: { _id: 0 }
    }
]);

Output:

{
    "productType" : [
        {
            "name" : "Car",
            "count" : 2,
            "companies" : [
                {
                    "name" : "Suzuki",
                    "count" : 1,
                    "models" : [
                        {
                            "name" : "s1",
                            "count" : 1
                        }
                    ]
                },
                {
                    "name" : "Maruti",
                    "count" : 1,
                    "models" : [
                        {
                            "name" : "m1",
                            "count" : 1
                        }
                    ]
                }
            ]
        },
        {
            "name" : "Bike",
            "count" : 4,
            "companies" : [
                {
                    "name" : "yamaha",
                    "count" : 3,
                    "models" : [
                        {
                            "name" : "y2",
                            "count" : 1
                        },
                        {
                            "name" : "y1",
                            "count" : 2
                        }
                    ]
                },
                {
                    "name" : "bajaj",
                    "count" : 1,
                    "models" : [
                        {
                            "name" : "b1",
                            "count" : 1
                        }
                    ]
                }
            ]
        }
    ]
}

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.