0

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",
},
2
  • 2
    it will help if you add original document structure as it is not clear where the brand is located ... Commented Dec 1, 2021 at 21:13
  • @R2D2 { "_id":ObjectID( "617b0dbacda6cbd1a0403f68") "brand": "6178524a5ff14e633aeff1ea", "SerialNumber": "45454234324", "ram": "4gb", }, { "_id":ObjectID( "617b0dbacda6cbd1a040345") "brand": "6178524a5ff14e633aeff1ea", "SerialNumber": "azazz5245454az", "ram": "8gb", }, Commented Dec 1, 2021 at 21:32

1 Answer 1

1

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

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

9 Comments

thank it works fine but couldt find a solution to add the sum like this itried to project $sum but result always 0 i want it to look like this { "brand" : "sony", "16gb" : 2, "8gb" : 1, "sum" :3}
ive tried it but its given wrong sum same in your example sony sum should be 2 but its 3
aaah my mistake I misunderstood , thought you need sum of objects ...
its giving the highest sum every time i think
|

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.