按日期间隔划分的MongoDB组

按日期间隔划分的MongoDB组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一个带有datetime字段和count字段的集合: { _id: null, datetime: new Date(), count: 1234 } 我想以24小时、7天和30天为间隔获得计数的总和。 结果必须如下所示: {"sum": 100, "interval": "day"}, {"sum": 700, "interval": "week"}, {"sum": 3000, "interval": "month"} 编辑: 更抽象:我需要按多个条件对结果进

我有一个带有datetime字段和count字段的集合:

{
    _id: null,
    datetime: new Date(),
    count: 1234
}
我想以24小时、7天和30天为间隔获得计数的总和。 结果必须如下所示:

{"sum": 100, "interval": "day"},
{"sum": 700, "interval": "week"},
{"sum": 3000, "interval": "month"}
编辑:

更抽象:我需要按多个条件对结果进行分组(在本例中为多个时间间隔)

MySQL示例:

SELECT 
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 24 HOUR, 1, 0) last_day,
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 168 HOUR, 1, 0) last_week,
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 720 HOUR, 1, 0) last_month,
    SUM(count) count
FROM table
GROUP BY    last_day,
            last_week,
            last_month
在MongoDB的聚合框架中有很多可用的方法。例如,运算符用于从分组中使用的日期获取该值:

db.collection.aggregate([
{“$组”:{
“_id”:{“$dayOfYear”:“$datetime”},
“总计”:{“$sum”:“$count”}
}}
])
或者你可以使用日期数学方法代替。通过应用历元日期,可以将日期对象转换为可以应用数学的数字:

db.collection.aggregate([
{“$组”:{
“_id”:{
“$subtract”:[
{“$subtract”:[“$datetime”,新日期(“1970-01-01”)],
{“$mod”:[
{“$subtract”:[“$datetime”,新日期(“1970-01-01”)],
1000 * 60 * 60 * 24
]}
]
},
“总计”:{“$sum”:“$count”}
}}
])

如果您所追求的是从当前时间点开始的间隔,那么您需要的基本上是日期数学方法,并通过运算符在某些条件下工作:

db.collection.aggregate([
{“$match”:{
“日期时间”:{
“$gte”:新日期(新日期().valueOf()-(1000*60*60*24*365))
}
}},
{“$组”:{
“_id”:空,
“24小时”:{
“$sum”:{
“$cond”:[
{“$gt”:[
{“$subtract”:[“$datetime”,新日期(“1970-01-01”)],
新日期().valueOf()-(1000*60*60*24)
]},
“$count”,
0
]
}
},
“30天”:{
“$sum”:{
“$cond”:[
{“$gt”:[
{“$subtract”:[“$datetime”,新日期(“1970-01-01”)],
新日期().valueOf()-(1000*60*60*24*30)
]},
“$count”,
0
]
}
},
“一年”:{
“$sum”:{
“$cond”:[
{“$gt”:[
{“$subtract”:[“$datetime”,新日期(“1970-01-01”)],
新日期().valueOf()-(1000*60*60*24*365)
]},
“$count”,
0
]
}
}
}}
])
它本质上与SQL示例相同,在SQL示例中,查询有条件地评估日期值是否在所需范围内,并决定是否将该值添加到总和中

这里的一个附加阶段是限制查询只对那些可能在您请求的最长一年范围内的项目进行操作的附加阶段。这使得它比前面介绍的SQL要好一点,因为可以使用索引过滤掉这些值,而不需要通过集合中的不匹配数据进行“暴力”


在使用聚合管道时,最好限制输入。

有两种不同的方法。一种是为每个范围发出单独的查询。这非常简单,如果对datetime字段进行索引,速度会很快


第二种方法是使用与SQL示例类似的方法将它们组合到一个查询中。要做到这一点,您需要使用该方法,创建一个管道,为新的“last_day”、“last_week”和“last_month”字段创建0或1值,然后使用运算符进行求和。

我不需要每天的求和。我只需要这三个时间间隔的总和。@jonasax那么你认为你在做什么?你在期待什么?所有总和都在一个查询结果中,或者运行单独的查询可以吗?你需要解释一下你对结果的期望。我希望得到每个间隔(天、周、月)的三个条目作为结果。理想情况下,在一个查询中。@jonasax一旦你解释清楚,这是非常可能的。MongoDB的方法非常相似。