【问题标题】:Get data where DateTime is a 15m interval获取 DateTime 为 15m 间隔的数据
【发布时间】:2014-11-16 15:06:02
【问题描述】:

我目前有一个类似这样定义的 Entry 模型:

    field :var_name, type: String
    field :var_data, type: String
    field :var_date, type: DateTime

我全天都有数据生成,并被要求每隔 15 分钟返回一份数据报告。 DataTime 字段 var_date 以 15 分钟为间隔的所有条目。即 12:00 12:15 12:30 12:45

我觉得这可能很简单,但目前很难处理,谁能帮忙。

我拥有的 var_date 中的一些示例数据是这样的:

    2014-09-18T05:00:00+00:00
    2014-09-18T05:05:00+00:00
    2014-09-18T05:10:00+00:00
    2014-09-18T05:15:00+00:00
    2014-09-18T05:20:00+00:00
    2014-09-18T05:25:00+00:00

【问题讨论】:

  • 您要生成什么报告?最容易通过示例向您展示。
  • 因此,您可以使用模运算符和 where 子句来执行此操作。第一个过程是从日期时间戳中提取时间。然后为每个间隔创建模运算。
  • 为什么不使用crontab
  • @dddd1919 我在每天结束时得到一批数据,必须对其进行排序。
  • @wdberkeley 该报告只是 var_name、var_data、var_date 的列表,其中 var_date 的时间间隔为 15 分钟一小时。即一小时后的 0、15、30 或 45 分钟。示例输出为:Process Time 133 2014-09-18T05:15:00+00:00

标签: ruby mongodb mongodb-query mongoid aggregation-framework


【解决方案1】:

MongoDB aggregation framework 是您的答案。您可以使用纪元时间戳作为输出值,也可以接受通用日期聚合运算符:

假设这里有一个名为Entry 的“类”,使用.collection 访问器来获取底层驱动程序函数。

这可以使用date aggregation operators

Entry.collection.aggregate([
    { "$group" => {
        "_id" => {
            "dayOfYear" => { "$dayOfYear" => "$var_date" },
            "interval" => {
                "$subtract" => [
                    { "$minute" => "$var_date" },
                    { "$mod" => [
                       { "$minute" => "$var_date" },
                       15
                    ]}
                ]
            }
        },
       "count" => { "$sum" => 1 }
    }}
])

或者在基本的“纪元时间戳”形式中,通过从初始纪元值中减去当前日期对象值来以数字形式表示时间戳:

Entry.collection.aggregate([
    { "$group" => {
        "_id" => {
            "$subtract" => [
                { "$subtract" => [ "$var_date", DateTime.new(1970,1,1) ] },
                { "$mod" => [
                    { "$subtract" => [ "$var_date", DateTime.new(1970,1,1) ] },
                    1000 * 60 * 15
                ]}
            ]
        },
        "count" => { "$sum" => 1 }
    }}
 ])

因此,在每种情况下,此处用于分组的_id 表示一小时内的 15 分钟间隔,您希望包含的任何字段都应用于"grouping operators" 以实现总计或其他功能,如示例期间内的“计数”事件。

无论如何,您需要查看聚合框架运算符,特别是 $group 作为管道阶段来累积结果。

【讨论】:

  • 感谢您的回答,我无法根据需要进行此操作。聚合框架似乎真的很强大。我今天早上使用这个例子作为起点,但想到了一种更简单的方法来获得我需要的结果,我已经在我自己的答案中发布了。关于 Mongodb 的更深层次的功能,我认为还有很多东西要学习。
  • @KevinMann 我基本上建议的是“你真的想要你提出的作为可能的答案吗?”我不认为你这样做。如果您真的想要定时组间隔,那么您希望它们保持一致并基于实际的小时间隔。您也希望在您的应用程序客户端上进行此处理,就像您的代码所做的那样。在我一直这样做的这些年里,普遍的看法是“数据库”服务器比应用程序服务器更强大。这延伸到“集群/分片”环境。让“数据库”完成工作。这很聪明。
  • @KevinMann 对帖子的“评论”限制再发表一条评论。关键是“看起来像什么”更少的代码行几乎从来没有更有效率。花了足够的时间编写汇编程序才知道这是真的。
  • 感谢您让数据库完成这项工作听起来是个好建议。对于这个特定的项目,我确实希望在 00、15、30 和 45 分钟得到结果。它基于在这些时隙对数据进行采样。我确实理解更少的代码行代码效率并不高,这就是为什么我在回答中寻求建议的原因,您的 cmets 对此有所帮助。我会考虑在数据库级别做更多的工作。
  • @KevinMann 这里的模运算符意味着这个数字应该可以被 15 倍“整除”。所以 15,30 和 45 都可以。这是有道理的,因为 15 实际上是从 0 到 15 的分组。如果您现在了解这是如何完成的。
【解决方案2】:

说明


今天早上几个小时后,我按照另一个答案的建议尝试使用 MongoDB 聚合框架,最终以更简单的代码方式执行此操作。

不知道为什么我昨天没有想到它,这可能效率不高(希望对此提出建议),但基本上对于每个Entry,我只是检查了var_date 字段的分钟,看看它是否有效匹配任何 15 分钟间隔。

0, 15, 30 or 45

如果有,我将其添加到 @entries15min,这为我提供了所需的数据。

我最终得到的代码


entries = Entry.all.order('var_date ASC')

@entries15min = []

entries.each do |entry|
  if [0,15,30,45].include? entry.var_date.min
    @entries15min << entry
  end
end

感谢您的所有建议,希望这对其他人有所帮助。

【讨论】:

  • 虽然这是对我的特定问题有效的答案并且考虑到我工作的环境,但我相信 Neil Lunn 的答案可能会证明是一个更好的答案。但是,我还没有根据该答案创建一个可行的解决方案,因此将其标记为我所知道的答案,它适用于我的问题和对数据库访问的限制。
猜你喜欢
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 2020-01-31
相关资源
最近更新 更多