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 根据 DayHour 对数据进行分组。您可以在 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?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现mongodb中的sum汇总操作?

用matlab对数据分类汇总

具有不同 $match 的嵌套 $group

Group_by / 按函数内的两个变量汇总

每天计算和汇总不同的值

关于C#中group by如何实现多条件分组汇总