MongoDB聚合-将数据分为时间段

时间:2018-09-21 13:46:22

标签: mongodb aggregation-framework grouping bucket

所以我有一些看起来像这样的数据:

[
    {
        "_id": "5ba41d8c5f60a647fc792c28",
        "key": "CPU Usage",
        "signaler": "lookup",
        "time": "2018-09-20T22:22:04.515Z",
        "status": "alarm"
    },
    {
        "_id": "5ba41d8c5f60a647fc792c2a",
        "key": "NETWORK Usage",
        "signaler": "engine",
        "time": "2018-09-20T22:22:04.516Z",
        "status": "warning"
    },
    {
        "_id": "5ba41d8c5f60a647fc792c29",
        "key": "NETWORK Usage",
        "signaler": "engine",
        "time": "2018-09-09T22:22:04.516Z",
        "status": "alarm"
    },
    {
        "_id": "5ba41d8c5f60a647fc792c2d",
        "key": "CPU Usage",
        "signaler": "evaluator",
        "time": "2018-09-09T22:22:04.840Z",
        "status": "alarm"
    },
    {
        "_id": "5ba41d8c5f60a647fc792c2b",
        "key": "RAM Usage",
        "signaler": "engine",
        "time": "2018-09-01T22:22:04.840Z",
        "status": "alarm"
    }
]

keysignaler可以是任何字符串,status必须是alarmwarningnormal中的一个。

我想编写一个汇总,将signaler + key分组,并告诉我三个时间段(全部时间,上周和上个月)的总警报和警告。

预期输出:

[
    {
        "_id": {
            "signaler": "lookup",
            "key": "CPU Usage"
        },
        "alarmsWeek": 1,
        "warningsWeek": 0,
        "alarmsMonth": 1,
        "warningsMonth": 0,
        "alarmsAllTime": 1,
        "warningsAllTime": 0
    },
    {
        "_id": {
            "signaler": "engine",
            "key": "Network Usage"
        },
        "alarmsWeek": 0,
        "warningsWeek": 1,
        "alarmsMonth": 1,
        "warningsMonth": 1,
        "alarmsAllTime": 1,
        "warningsAllTime": 1       
    },
    {
        "_id": {
            "signaler": "evaluator",
            "key": "CPU Usage"
        },
        "alarmsWeek": 0,
        "warningsWeek": 0,
        "alarmsMonth": 1,
        "warningsMonth": 0,
        "alarmsAllTime": 1,
        "warningsAllTime": 0       
    },
    {
        "_id": {
            "signaler": "engine",
            "key": "RAM Usage"
        },
        "alarmsWeek": 0,
        "warningsWeek": 0,
        "alarmsMonth": 0,
        "warningsMonth": 0,
        "alarmsAllTime": 1,
        "warningsAllTime": 0       
    }
]

我知道如何编写用于计算所有时间警告和警报的小组赛段,但是我不确定如何进行时间段划分,特别是因为它们是“堆积”的,即上周的计数也将在上个月的计数。

据我所知,分组步骤是

[
    { 
        "$group": { 
            "_id": { 
                "signaler":"$signaler",
                "key": "$key"

            }, 
            "totalWarnings": {
                "$sum": {
                    "$cond": [
                        {"$eq": [ "warning", "$level" ] },
                        1,
                        0
                    ]
                } 
            }, 
            "totalAlarms": {
                "$sum": {
                    "$cond": [
                        {"$eq": [ "alarm", "$level" ] },
                        1,
                        0
                    ]
                } 
            }
        } 
    },
    {
        "$project": { 
            "_id": { "$concat": ["$_id.key", "+", "$_id.signaler"] },
            "key": "$_id.key",
            "signaler": "$_id.signaler",
            "totalAlarms": 1,
            "totalWarnings": 1
        }
    }
]

2 个答案:

答案 0 :(得分:1)

为说明Fanamy的答案,这是用于实现此目的的小组赛阶段:

db.collection.aggregate([
  { "$group": {
    "_id": { "signaler": "$signaler", "key": "$key" },
    "alarmsWeek": {
      "$sum": {
        "$cond": {
          "if": {
            "$and": [
              { "$eq": ["$status", "alarm"] },
              { "$lt": ["$time", { "$subtract": [new Date(), { "$multiply": [1000, 3600, 24, 7] }] }] }
            ]
          },
          "then": 1,
          "else": 0
        }
      }
    },
    "warningsWeek": {
      "$sum": {
        "$cond": {
          "if": {
            "$and": [
              { "$eq": ["$status", "warning"] },
              { "$lt": ["$time", { "$subtract": [new Date(), { "$multiply": [1000, 3600, 24, 7] }] }] }
            ]
          },
          "then": 1,
          "else": 0
        }
      }
    },
    "alarmsMonth": {
      "$sum": {
        "$cond": {
          "if": {
            "$and": [
              { "$eq": ["$status", "alarm"] },
              { "$lt": ["$time", { "$subtract": [new Date(), { "$multiply": [1000, 3600, 24, 30] }] }] }
            ]
          },
          "then": 1,
          "else": 0
        }
      }
    },
    "warningsMonth": {
      "$sum": {
        "$cond": {
          "if": {
            "$and": [
              { "$eq": ["$status", "warning"] },
              { "$lt": ["$time", { "$subtract": [new Date(), { "$multiply": [1000, 3600, 24, 30] }] }] }
            ]
          },
          "then": 1,
          "else": 0
        }
      }
    },
    "alarmsAllTime": {
      "$sum": { "$cond": { "if": { "$eq": ["$status", "alarm"] }, "then": 1, "else": 0 }}
    },
    "warningsAllTime": {
      "$sum": { "$cond": { "if": { "$eq": ["$status", "warning"] }, "then": 1, "else": 0 }}
    }
  }}
])

答案 1 :(得分:0)

对于时间段,您可以将https://docs.mongodb.com/manual/reference/method/Date/与$ subtract结合使用(因为它支持日期)https://docs.mongodb.com/manual/reference/operator/aggregation/subtract/

因此只需简单地获取当前日期,减去7天或30个月(实际上并不是“正确的月份”),然后检查文档的日期是否低于您创建的日期。