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}
}
])
$objectToArray
to extract the keys$filter
to keep only thetrue
ones$unwind
to separate the keys to different documents$group
to count each key- format the results Playground example