代码之家  ›  专栏  ›  技术社区  ›  user3690467

MongoDB聚合-将数据划分为时间桶

  •  0
  • user3690467  · 技术社区  · 7 年前

    所以我有一些数据是这样的:

    [
        {
            "_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"
        }
    ]
    

    key signaler 可以是任何字符串, status 一定是其中之一 alarm warning normal

    我想写一个聚合 + 钥匙

    预期产量:

    [
        {
            "_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 回复  |  直到 7 年前
        1
  •  1
  •   Ashh    7 年前

    为了说明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 }}
        }
      }}
    ])
    
        2
  •  0
  •   Fanamy    7 年前

    为了你能用的时间桶 https://docs.mongodb.com/manual/reference/method/Date/ 与$subtract结合使用(因为它支持日期) https://docs.mongodb.com/manual/reference/operator/aggregation/subtract/

    因此,只需取当前日期,减去7天或30天为一个月(这不是真正的“月正确”),并检查文件的日期是否低于您创建的日期。