从 mongodb $avg 中排除 0 个值但保留其他字段

eli*_*0tt 5 mongodb aggregation-framework

我在 MongoDB 3.2 上运行了一些聚合查询。我想按一个字段对文档进行分组,并在另一个数字字段上取平均值。我需要平均值来忽略 0 值。问题是我无法完全过滤文档,因为我需要另一个字段进行计数。

让我们举例说明:

这是我的文档的结构:

{"stringToGroupByOn":"foo", "valueToAvg":42, "valueToSum":21}
{"stringToGroupByOn":"foo", "valueToAvg":0, "valueToSum":13}
Run Code Online (Sandbox Code Playgroud)

我不能像这样过滤:

db.foobar.aggregate([
    { 
        $match : { valueToAvg : { $gt : 0 } } 
    },
    { 
        $group : {
            _id : '$stringToGroupByOn',
            avg : { $avg :  '$valueToAvg' }, 
            count : { $sum : '$valueToSum' }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

因为我失去了计数的值 13。

你认为有一种方法可以只在一个查询中做到这一点吗?

pro*_*r79 5

您可以在投影中使用 $cond 来设置 null 而不是0,因为在使用平均值时不考虑 null。

db.avg.aggregate([
   {$project:{
       _id:1,
       valueToSum:1,
       stringToGroupByOn:1,
       valueToAvg:{$cond: 
             { if: { $eq: [ "$valueToAvg", 0 ] }, 
                   then: null, 
                   else: "$valueToAvg" }}           
       }},
    { 
        $group : {
            _id : '$stringToGroupByOn',
            avg : { $avg :  '$valueToAvg' }, 
            count : { $sum : '$valueToSum' }
        }
    }
Run Code Online (Sandbox Code Playgroud)

输出:

{
    "_id" : "foo",
    "avg" : 42.0,
    "count" : 34.0
}
Run Code Online (Sandbox Code Playgroud)