MongoDB:如何聚合可能缺失的数组字段

时间:2013-10-29 21:32:40

标签: mongodb aggregation-framework

如果数组字段可能完全丢失(如第10个月的情况),如何让MongoDB计算数组值的总和?

例如:

> 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
}

如何在上述结果中显示第10个月(将“总数”显示为0)?

奖金:如何让上述内容显示可用的工作日(NumWeekdays减去假期总和)?

我已经尝试过$ project将数据转换为规范格式,但到目前为止还没有成功......谢谢!

1 个答案:

答案 0 :(得分:0)

$unwind并未通过MonthNum 10传递您的文档,因为您的Holidays数组在该文档中为空(请参阅{{3}底部的注释})。 假设 Holidays始终是包含至少一个项目或完全不在文档中的数组,您可以使用$project内的$unwind docs添加"假日"只有NumDays = 0到您的Holidays的文档为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"]}}}
]);

请注意,$ifNull如果您的某些文档Holidays是空数组,则无法正常工作;它必须完全缺席。