How do I get MongoDB to calculate the sum of array values when the array field may be missing completely (as is the case for month 10)?
For example:
> db.month.save({MonthNum: 10,
... NumWeekdays: 23});
> db.month.save({MonthNum: 11,
... NumWeekdays: 21,
... Holidays: [ {Description: "Thanksgiving", NumDays: 2} ] });
> db.month.save({MonthNum: 12,
... NumWeekdays: 22,
... Holidays: [ {Description: "Christmas", NumDays: 6},
... {Description: "New Year's Eve", NumDays: 1} ] });
> db.month.aggregate( { $unwind: "$Holidays" },
... { $group: { _id: "$MonthNum",
... total: { $sum: "$Holidays.NumDays" } } });
{
"result" : [
{
"_id" : 12,
"total" : 7
},
{
"_id" : 11,
"total" : 2
}
],
"ok" : 1
}
How do I get month 10 to show up in the above results (showing "total" as 0)?
Bonus: How do I get the above to show the available weekdays (the NumWeekdays minus the sum of the Holidays)?
I've tried $project to get the data into a canonical format first but without success so far... thanks!
$unwind
isn't passing along your document with MonthNum
10 because your Holidays
array is empty on that document (see the note at the bottom of the $unwind
docs ). Assuming that Holidays
is always either an array containing at least one item or completely absent from a document, you can use the $ifNull
operator inside of $project
to add a "Holiday" document that just has NumDays = 0 to your Holidays
is null:
db.month.aggregate([
// Make "Holidays" = [{NumDays:0}] if "Holidays" is null for this document (i.e. absent)
{$project:{NumWeekDays:1, MonthNum:1, Holidays:{$ifNull:["$Holidays", [{"NumDays":0}]]}}},
// Now you can unwind + group as normal
{$unwind:"$Holidays"},
{$group:{_id:"$MonthNum", NumWeekDays:{$first:"$NumWeekDays"}, "total":{$sum:"$Holidays.NumDays"}}},
// This should take care of "available weekdays"
{$project:{total:1, available:{$subtract:["$NumWeekDays", "$total"]}}}
]);
Note that $ifNull
won't work if for some of your documents Holidays
is an empty array; it has to be absent completely.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.