SpawN
SpawN

Reputation: 55

mongodb count num of distinct values for each object

Hello i am creating a new Web Application for products selling using MEAN stack and i want to see for every brand (HP,ASUS..) how many pc have 8 Gb , how many PC have 4 GB etc. so this is my code

exports.allcountProduct = async (req, res) => {
try {
    const count = await Product.aggregate(

            {
                "$group": {
                    "_id": {
                        $toLower: "$ram"
                    },
                    "count": { "$sum": 1 }
                }
            },
            {
                "$group": {
                    "_id": null,
                    "counts": { "$push": { "k": "$_id", "v": "$count" } }
                }
            },
            {
                "$replaceRoot": {
                    "newRoot": { "$arrayToObject": "$counts" }
                }
            },

        ],

    )

    res.json(count);
}

and what im getting is :

 [
{
    "4GB": 20,
    "8GB": 15,
    "16GB": 32
}

]

so im getting is the results of all the brands while what im trying to get is every brand alone like this :

   [
{
    "brand": "ASUS",
    "8GB": 6,
    "16GB": 14
}

]

this is an example from the document :

{
"_id":ObjectID( "617b0dbacda6cbd1a0403f68")
"brand": "6178524a5ff14e633aeff1ea",
"SerialNumber": "45454234324",
"ram": "4gb",
},
{
"_id":ObjectID( "617b0dbacda6cbd1a040345")
"brand": "6178524a5ff14e633aeff1ea",
"SerialNumber": "azazz5245454az",
"ram": "8gb",
},

Upvotes: 0

Views: 204

Answers (1)

R2D2
R2D2

Reputation: 10737

Maybe something like this:

mongos> db.b.aggregate([
{$group:{ _id:{ r:"$ram" ,b:"$brand"}, cnt:{$sum:1} }}  ,
{$project:{ a:[{k:"$_id.r" ,v:"$cnt"}] , brand:"$_id.b" ,_id:0}   },
{$project:{d:{$arrayToObject:"$a"} ,brand:1 }  } ,
{$group:{ _id:"$brand", ram:{$push:"$d"}  }} ,
{$project:{_id:0,brand:"$_id" ,"options": { $mergeObjects: "$ram" } }},
{$replaceRoot: {  newRoot: { $mergeObjects: ["$$ROOT", "$options"] }}}, 
{$project:{options:0}}   ]).pretty()

{ "brand" : "6178524a5ff14e633aeff1ea", "8gb" : 1, "4gb" : 1 }
{ "brand" : "sony", "16gb" : 2, "8gb" : 1 }
mongos> 

explained:

  1. group by ram and brand so we count how much per brand per ram size
  2. project the ram type and ram count to k & v suitable for next stage to join as object
  3. Convert k,v arrays to object
  4. Group by brand so we can have a list per ram size & count
  5. Switch the array with ram types/counts to object
  6. Flatten the object to the root object
  7. project only the needed fields as per our needs

playground

Upvotes: 1

Related Questions