Mongo每天汇总$group?
Posted
技术标签:
【中文标题】Mongo每天汇总$group?【英文标题】:Mongo aggregate $group by each day? 【发布时间】:2021-09-07 13:37:28 【问题描述】:我有一个历史集合,并希望基于该集合创建导出数据库
[
_id: "...",
value: 10,
at: ISODate("2021-24-06T00:01:02.023")
,
_id: ...,
value: 13,
at: ISODate("2021-24-06T00:04:11.211")
,
_id: ...,
value: 12,
at: ISODate("2021-24-06T09:11:31.182")
,
_id: ...,
value: 40,
at: ISODate("2021-24-07T01:33:31.723")
,
_id: ...,
value: 40,
at: ISODate("2021-24-15T09:32:44.983")
,
_id: ...,
value: 40,
at: ISODate("2021-24-16T10:43:22.083")
,
_id: ...,
value: 40,
at: ISODate("2021-24-16T14:43:22.083")
,
_id: ...,
value: 40,
at: ISODate("2021-24-17T04:25:12.021")
,
_id: ...,
value: 40,
at: ISODate("2021-24-18T20:13:22.083")
,
_id: ...,
value: 40,
at: ISODate("2021-24-19T18:41:22.083")
]
我必须按小时、天、周公开 3 个选项组
我正在尝试使用 $group 来计算一天中的混合/最大值或平均值,但不知道如何将它们分组到每小时/每天/每周的数据中
我可以按 $cond 分组吗? 因为它对所有情况都非常灵活。
示例:按小时分组,第一时刻 = 2021-24-06T00:00:00.000 期望:
[
at: ISODate("2021-24-06T00:00:00.000"),
max: 13,
min: 10,
avg: 21.5
,
at: ISODate("2021-24-06T01:00:00.000"),
, ...,
at: ISODate("2021-24-06T09:00:00.000"),
max: 12,
min: 12,
avg: 12
]
分组依据 = 天
预期:
[
at: ISODate("2021-24-06T00:00:00.000"),
max: 13,
min: 10,
avg: 11.7
,
at: ISODate("2021-24-07T00:00:00.000"),
max: 40,
min 40,
avg: 40,
]
这是我的想法。创建每个组的第一个时刻,将at
与组的第一个时刻和最后一个时刻进行比较。
例如:按天分组,第一组的第一时刻在:ISODate("2021-24-06T00:00:00.000")
-> 最后时刻 = ISODate("2021-24-06T23:59:59.999")
-> 分组所有记录属于该组
第二组:ISODate("2021-24-06T00:00:00.000")
+ 1day = ISODate("2021-24-07T00:00:00.000")
-> 最后时刻 = ISODate("2021-24-07T23:59:59.999")
-> 组所有记录属于该组
但是如何实现
【问题讨论】:
docs.mongodb.com/manual/reference/operator/aggregation/…希望这有帮助! 使用 $bucket,预先计算您想要聚合的范围并明确传递它们。 @D.SM 哦,这似乎是个好建议。我会尝试并在下一条评论中报告 @D.SM 工作顺利,非常感谢 【参考方案1】:您可以在 Group By $group
子句中使用 $dateToString
根据 Day
和 Hour
对数据进行分组。您可以在 Group By $group
子句中使用 $week
根据 Week
对数据进行分组。
请看下面的代码:
样本数据
按周分组
db.collData.aggregate([
$group :
_id : $week: '$at' ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
按天分组
db.collData.aggregate([
$group :
_id : $dateToString: format: "%Y-%m-%d", date: "$at" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
按小时分组
db.collData.aggregate([
$group :
_id : $dateToString: format: "%Y-%m-%dT%H", date: "$at" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
See more details about the $group
See more details about the $dateToString
See more details about the $week
在查询中使用 TimeZone 更新
您可以在$dateToString
表达式中使用timezone
。请检查以下示例:
db.collData.aggregate([
$group :
_id : $dateToString: format: "%Y-%m-%d", date: "$at", timezone: "-05:00" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
db.collData.aggregate([
$group :
_id : $dateToString: format: "%Y-%m-%d", date: "$at", timezone: "+07:00" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
您将在下面的链接中找到有关该表达式的更多信息,包括timezone
。
MongoDB $dateToString
timezone
在小时示例中添加:
db.collData.aggregate([
$group :
_id : $dateToString: format: "%Y-%m-%dT%H", date: "$at", timezone: "+00:30" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
timezone
添加在周示例中:
db.collData.aggregate([
$group :
_id : $week: date: '$at', timezone: "-05:00" ,
averageValue: $avg: "$value" ,
count: $sum: 1
,
$sort : averageValue: -1
])
【讨论】:
我需要按天和奇数小时对数据进行分组,因为 timeZone 不是 UTC +0。例如:按时区 +7 的 2022-12-16 日分组 => 我必须从 UtC +0 的 2022-12-15T14:00:00 到 2022-12-16T13:59:59 获取数据。这就是为什么我不能使用 $group 和 $dateToString,时区可能是 UTC +0.5 所以最小单位是分钟 @VũAnhDũng,请检查答案的更新部分。表达式$dateToString
允许timezone
。
一周怎么样?它还支持时区吗?我可以分组的时间甚至 timeZone 是 +0.5。必须从 0:30 -> 1:30、1:30 -> 2:30 ... 分组
我已通过在小时和周示例中添加 timezone
来更新答案。
我已经完成了使用 $bucket 并尝试了使用 $group 的解决方案。结果是一样的,非常好。我将比较两种方式的性能并选择更好的性能。非常感谢@csharpbd以上是关于Mongo每天汇总$group?的主要内容,如果未能解决你的问题,请参考以下文章