Reputation: 6988
I have seen lots posts to using aggregate
to sum
nested ARRAY
fields, I tried using it with my nested object which did not work.
When I query, the data structure is something like...
[
{
"key": "value",
"more_key": "more_value",
"meals": {
"A": {
"name": "salmon",
"amount": "8"
},
"B": {
"name": "vege",
"amount": "6"
},
}
},
{
"key": "value",
"more_key": "more_value",
"meals": {
"A": {
"name": "salmon",
"amount": "8"
},
"B": {
"name": "vege",
"amount": "6"
},
"C": {
"name": "other meal",
"amount": "6"
},
}
},
];
I am trying to sum the amount
I have tried something like this...
await Model.aggregate([
{ $match: { isDeleted: false } },
{ $unwind: '$meals' }, // tried with + without this
{ $group: { _id: null, sum: { $sumA: '$meals.A.amount', $sumB: '$meals.B.amount' } } }
]);
Can someone give me some advice and suggestion on how this can be done?
Thanks in advance.
Upvotes: 1
Views: 701
Reputation: 878
There are a few things going on here:
1) $unwind
doesn't work on objects, only on arrays. You can fix this by converting your meals object to an array with $objectToArray
2) Your amount field looks like it is of type String so will need to be converted to a number for summing
Here is an aggregation that does what you need:
await Model.aggregate([
// Convert meals object to array
{ $project: { meals: { $objectToArray: '$meals' }}},
// unwind meals array
{ $unwind: '$meals' },
// convert meals.v.amount to integer and sum them (the v is shorthand for values)
{ $group: {
_id: null,
total: {
$sum: {
$convert: {
input: '$meals.v.amount',
to: 'int'
}
}
}
}}
])
You could change _id of $group to _id: meals.k
to sum by the keys of the meals object i.e A, B, C
Upvotes: 2