【问题标题】:MongoDB Aggregation group and count stringsMongoDB聚合组和计数字符串
【发布时间】:2015-02-14 12:19:11
【问题描述】:

我在从我的收藏中计算不同的 LogStatusse 时遇到问题。我想从查询中得到以下结果:

月 |进口商名称 | NrOfError | NrOfDebug | NrOfInfo | NrOfWarning

因此,这包括按月份和 ImporterName 分组,并计算具有不同状态的文档数量。

我的 MongoDB 收藏:

{
    "_id" : "8ec84cb7-5099-4a9d-be00-a40200a67c5a",
    "Messages" : [
        {
            "LogStatus" : "Error",
            "Message" : "My test message"
        },
        {
            "LogStatus" : "Error",
            "Message" : "My test message"
        },
        {
            "LogStatus" : "Error",
            "Message" : "My test message"
        },
        {
            "LogStatus" : "Error",
            "Message" : "My test message"
        },
        {
            "LogStatus" : "Error",
            "Message" : "My test message"
        }
    ],
    "StartTime" : new Date("2014-12-15T10:06:09.00Z"),
    "EndTime" : new Date("2014-12-15T13:06:09.00Z"),
    "HasErrors" : true,
    "HasWarnings" : false,
    "ImporterName" : "MyImporter"
}

我已经有以下查询:

db.SessionLogItems.aggregate
([
{
    $project:
    {
        month :{$month : "$StartTime"},
        name: "$ImporterName",
        status: "$Messages.LogStatus", 
        _id: 0
    }
}
])

结果:

月:12,“名称”:“进口商名称”,状态:[“错误”,“错误”,“信息”]

db.SessionLogItems.aggregate
([
{ 
    $unwind: "$Messages" 
}, 
{
    $group: { _id: "$Messages", Number : {$sum : 1 }}
}, 
{
    $sort: {Number : -1 }
} 
])

结果: “_id”:{“LogStatus”:“警告”,“消息”:“我的测试警告”},“数字”:5 "_id" : { "LogStatus" : "Error", "Message" : "我的测试消息" }, "Number" : 5

但我似乎无法找出正确的查询。任何帮助表示赞赏!

编辑:

我上面的示例只是众多文档之一。我有几个具有 startTime 和 EndTime 的进口商。进口商有几个日志消息和四个可能的日志状态:“错误”、“信息”、“调试”、“警告”。我想了解每个进口商每月和每个进口商产生了多少错误、信息、调试和警告。

【问题讨论】:

  • 那你在这里问什么?所有项目都有一个“错误”的LogStatus。您是否只希望对找到的每个不同的日志状态进行计数?在整个集合中还是仅在每个文档中?这个问题似乎缺乏这种清晰度,也没有提供不同数据或结果的明确示例。可以使用一些工作来更好地解释。
  • 我的坏。我上面的示例只是众多文档之一。我有几个具有 startTime 和 EndTime 的进口商。进口商有几个日志消息和四个可能的日志状态:“错误”、“信息”、“调试”、“警告”。我想了解每个进口商每个月和每个进口商产生了多少错误、信息、调试和警告。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

假设StartTimeEndTime 值之间的“月份”没有重叠,那么您可以简单地使用StartTime 值作为分组键的基础。其他“字段”的大部分魔法来自 $cond 运算符,它决定是否计算值:

db.SessionLogItems.aggregate([

    // Unwind the array to de-normalize the documents contained
    { "$unwind": "$Messages" },

    // Month and Importer form the grouping key
    { "$group": {
        "_id": { 
            "month": { "$month": "$StartTime" },
            "ImporterName": "$ImporterName"
        },
        "NrOfError": {
           "$sum": {
               "$cond": [
                   { "$eq": [ "$Messages.LogStatus", "Error" ] },
                   1,
                   0
                ]
            }
        },
        "NrOfDebug": {
           "$sum": {
               "$cond": [
                   { "$eq": [ "$Messages.LogStatus", "Debug" ] },
                   1,
                   0
                ]
            }
        },
        "NrOfInfo": {
           "$sum": {
               "$cond": [
                   { "$eq": [ "$Messages.LogStatus", "Info" ] },
                   1,
                   0
                ]
            }
        },
        "NrOfWarning": {
           "$sum": {
               "$cond": [
                   { "$eq": [ "$Messages.LogStatus", "Warning" ] },
                   1,
                   0
                ]
            }
        }
    }}
])

所以基本上“状态”值是经过测试的,如果匹配或不匹配,则将适当的计数值添加到适当的字段中。

【讨论】:

  • 现在测试它。谢谢你的解释。我错过了 $cond 运算符。查询成功后我会报告。
  • @user4169993 这是一个简单的错字,现已更正。只是一个额外的支架。一种罕见的情况是我在提交之前没有针对您的数据运行代码。我还更正了您的示例数据,这些数据对于某人粘贴到集合中进行测试是无效的。
  • 非常感谢,我正在测试它并返回错误。现在完美了!非常感谢您的时间和智慧!
猜你喜欢
  • 2020-11-27
  • 2019-03-03
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
  • 2016-12-25
  • 2014-02-27
  • 2013-11-23
  • 1970-01-01
相关资源
最近更新 更多