I have a load of documents in mongodb which look something like this:
[
{
name: "steve",
accountFeatures: {word: true, excel: false, powerpoint: true}
},
{
name: "john",
accountFeatures: {word: false, excel: true, powerpoint: true, notes: true}
},
{
name: "rick",
accountFeatures: {word: true, excel: false, powerpoint: true}
}
]
I want to run an aggregation to find out how many of each of the keys in the objects are set to true (there are many more keys in the actual data), so the expected output for the sample data would be:
{
"res": {
"excel": 1,
"notes": 1,
"powerpoint": 3,
"word": 2
}
}
Is this possible? So far all I can think to do is this:
[
{
'$project': {
'_id': 0,
'accountFeatures': 1
}
]
CodePudding user response:
You can use $objectToArray and $unwind which will allow us $group by the keys:
db.collection.aggregate([
{
$set: {accountFeatures: {$objectToArray: "$accountFeatures"}}
},
{
$project: {
accountFeatures: {
$filter: {
input: "$accountFeatures",
as: "item",
cond: {$eq: ["$$item.v", true]}
}
}
}
},
{
$unwind: "$accountFeatures"
},
{
$group: {_id: "$accountFeatures.k", v: {$sum: 1}}
},
{
$group: {_id: 0, data: {$push: {k: "$_id", v: "$v"}}}
},
{
$project: {res: {$arrayToObject: "$data"}, _id: 0}
}
])
$objectToArrayto extract the keys$filterto keep only thetrueones$unwindto separate the keys to different documents$groupto count each key- format the results Playground example
