MongoDB 聚合 - 将数据分成时间段
MongoDB Aggregations - Divide data into time buckets
所以我有一些数据如下所示:
[
{
"_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
之一。
我想写一个聚合,它在 signaler
+ key
上分组并告诉我 3 个持续时间的总警报和警告:所有时间、上周和上个月。
预期输出:
[
{
"_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
}
]
我知道如何编写小组赛阶段计算所有时间的警告和警报,但我不确定如何进行时间分桶,尤其是因为它们是 'stacked' 即上周的计数也将计入上个月的统计。
据我了解的组步骤:
[
{
"$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
}
}
]
您可以使用的时间段 https://docs.mongodb.com/manual/reference/method/Date/ in combination with $subtract (as it supports dates) https://docs.mongodb.com/manual/reference/operator/aggregation/subtract/
所以只需使用当前日期,减去 7 天或一个月减去 30 天(实际上不会 "month-correct")并检查文档的日期是否早于您的创建日期。
为了说明 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 }}
}
}}
])
所以我有一些数据如下所示:
[
{
"_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
之一。
我想写一个聚合,它在 signaler
+ key
上分组并告诉我 3 个持续时间的总警报和警告:所有时间、上周和上个月。
预期输出:
[
{
"_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
}
]
我知道如何编写小组赛阶段计算所有时间的警告和警报,但我不确定如何进行时间分桶,尤其是因为它们是 'stacked' 即上周的计数也将计入上个月的统计。
据我了解的组步骤:
[
{
"$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
}
}
]
您可以使用的时间段 https://docs.mongodb.com/manual/reference/method/Date/ in combination with $subtract (as it supports dates) https://docs.mongodb.com/manual/reference/operator/aggregation/subtract/
所以只需使用当前日期,减去 7 天或一个月减去 30 天(实际上不会 "month-correct")并检查文档的日期是否早于您的创建日期。
为了说明 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 }}
}
}}
])