mongodb - 获取每个 "loglevel"的 "name"计数

标签 mongodb mongodb-query aggregation-framework

例如我有以下集合:

db.names.find({})

{ "_id" : ObjectId("5768d9b4bc6f464899594570"), "name" : "t1", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768d9d5bc6f464899594571"), "name" : "t1", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768d9dcbc6f464899594572"), "name" : "t1", "loglevel" : "WARNING" }

{ "_id" : ObjectId("5768d9dfbc6f464899594573"), "name" : "t1", "loglevel" : "WARNING" }

{ "_id" : ObjectId("5768d9e0bc6f464899594574"), "name" : "t1", "loglevel" : "WARNING" }

{ "_id" : ObjectId("5768d9e7bc6f464899594575"), "name" : "t1", "loglevel" : "INFO" }

{ "_id" : ObjectId("5768d9f3bc6f464899594576"), "name" : "t2", "loglevel" : "INFO" }

{ "_id" : ObjectId("5768d9f9bc6f464899594577"), "name" : "t2", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768da19bc6f464899594578"), "name" : "t2", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768da1abc6f464899594579"), "name" : "t2", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768da1bbc6f46489959457a"), "name" : "t2", "loglevel" : "ERROR" }

{ "_id" : ObjectId("5768e247bc6f46489959457b"), "name" : "t3", "loglevel" : "INFO" }

我已经尝试过,但我认为这应该是更好的解决方案(也可以省略 else)

db.names.aggregate(
    {$group: {
        _id: "$name",
        error: {$sum: {$cond: {if: {$eq: ['$loglevel', 'ERROR']}, then: {$sum: 1}, else: {$sum: 0}}}},
        warning: {$sum: {$cond: {if: {$eq: ['$loglevel', 'WARNING']}, then: {$sum: 1}, else: {$sum: 0}}}},
        info: {$sum: {$cond: {if: {$eq: ['$loglevel', 'INFO']}, then: {$sum: 1}, else: {$sum: 0}}}}
    }}
)

最佳答案

删除 if/else 条件 block 中的 { "$sum": 1 }{ "$sum": 0 } 表达式,将它们替换为值 1 和 0(分别针对每个条件 block )。

最终的管道应如下所示,使用其他 $cond 语法省略了 if/else block :

db.names.aggregate([
    {
        "$group": {
            "_id": "$name",
            "error": { 
               "$sum": { 
                   "$cond": [ { "$eq": [ "$loglevel",  "ERROR" ] }, 1, 0] 
               }
           },
           "warning":{
               "$sum": { 
                   "$cond": [ { "$eq": [ "$loglevel", "WARNING" ] }, 1, 0 ]
                }
           },
           "info": { 
               "$sum": { 
                   "$cond": [ { "$eq": [ "$loglevel",  "INFO" ] }, 1, 0 ]
               }
           }
        }
    }
])
<小时/>

或者动态创建管道,给定一组可能的状态:

var statuses = ["ERROR", "WARNING", "INFO"],
    groupOperator = { "$group": { "_id": "$name" } };

statuses.forEach(function (status){ 
    groupOperator["$group"][status.toLowerCase()] = { 
       "$sum": { 
           "$cond": [ { "$eq": [ "$loglevel",  status ] }, 1, 0] 
       }
   }
});

db.names.aggregate([groupOperator]);

输出

/* 1 */
{
    "_id" : "t1",
    "error" : 2,
    "warning" : 3,
    "info" : 1
}

/* 2 */
{
    "_id" : "t2",
    "error" : 4,
    "warning" : 0,
    "info" : 1
}

/* 3 */
{
    "_id" : "t3",
    "error" : 0,
    "warning" : 0,
    "info" : 1
}

关于mongodb - 获取每个 "loglevel"的 "name"计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43660871/

相关文章:

mongodb - 关系数据库与列式数据库和文档数据库——它们不是一回事吗?

mongodb - 从文档中删除空字段的名称

java - 为什么我的 Mongo 聚合不能在嵌套文档上正常工作?

node.js - 不在特定时间段内聚合数据

mongodb - 根据日期范围按日/月/周分组

javascript - Meteorjs collection.find 不会从数据库返回特定数据

linux - Web 服务器实例无法使用 aws ec2 linux : Connection refused 连接到 mongodb 实例

javascript - Mongoose批量插入子类别

node.js - Mongodb 聚合或投影

mongodb - 如何仅查看 Mongoose 中值的首字母来查找所有文档