【问题标题】:find record closest to a given time in ruby on rails在 ruby​​ on rails 中查找最接近给定时间的记录
【发布时间】:2012-01-30 22:55:37
【问题描述】:

背景

我有一个 ror 应用程序,它不断记录并在网站上显示实时传感器数据。然后我有一个名为 sensors 的表,其中包含所有传感器的唯一列表并存储最新值。

我还有另一个表历史记录,它转储了每个传感器接收到的所有传感器值。

所以关系是"sensor has many historys"time_stamp col记录了创建时间戳。

并非所有传感器都以相同的间隔或频率更新。

问题

现在我想从用户那里获取输入时间戳、过去的日期和时间,并显示当时传感器显示的内容。例如,假设我想查看昨天下午 2 点所有传感器的样子,一旦我从用户那里获得了这个时间戳,我如何从历史表中检索最接近输入时间戳的一个传感器值。

我希望在 Sensor 模型中添加一个方法,该方法将 time_stamp 作为参数,并从历史表中检索最接近输入 time_stamp 的值。

编写此活动记录查询的最简单方法是什么?

谢谢 肖纳克

【问题讨论】:

    标签: ruby-on-rails timestamp


    【解决方案1】:

    只需根据传递的时间戳和历史时间戳之间的差异(绝对值,因此它可以向任一方向)对历史进行排序,并返回顶部结果(即差异最小的那个)。

    sensor.histories.order("ABS(time_stamp - #{params[:time_stamp].to_i})").first
    

    请注意,对于此查询,我假设您使用的是 MySQL(因为我使用的是 MySQL 方法 ABS),并且我还假设 time_stamp 字段存储为 unix 时间戳,用户输入也是如此。如果数据库存储或输入格式不同,则必须使用不同的日期算术函数。有关详细信息,请参阅http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html。或者,如果您不使用 MySQL,请参阅您正在使用的数据库的文档。

    另外请注意,我正在使用.to_i 来清理我的查询数据。如果您的数据采用不同的格式,您可能需要以不同的方式对其进行清理。

    为了提高效率,请将其限制在最大可能范围内的 time_spans。如果传感器每 10 分钟或更频繁地获取数据(两次读数之间的间隔不得少于 10 分钟),那么每侧的范围大于 10 分钟就可以了。像下面的东西。这里,600 = 10(分钟)* 60(秒):

    sensor.histories.where("time_stamp >= ? AND time_stamp <= ?", params[:time_stamp].to_i - 600, params[:time_stamp].to_i + 600).order("ABS(time_stamp - #{params[:time_stamp].to_i})").first
    

    将其转换为模型方法很简单:

    class Sensor < ActiveRecord::Base
        def history_at(time_stamp)
            self.histories.where("time_stamp >= ? AND time_stamp <= ?", time_stamp.to_i - 600, time_stamp.to_i + 600).order("ABS(time_stamp - #{time_stamp.to_i})").first
        end
    end
    

    【讨论】:

    • 感谢您的快速回答!在关闭之前还有一件事,每个传感器每 10 分钟更新一次,我有大约一年的数据!所以每次我想读取一个传感器的值时,对整个事情进行排序会不会花费很多时间?有没有办法通过根据输入时间戳给出一些跨度来优化你告诉我的查询?我正在使用 MS SQL Server 2008。再次感谢!
    • 是的,您可以将其限制为仅考虑合理的时间戳。我用一些细节更新了我的答案。
    • 如果是多个传感器的查询呢?有没有一种方法可以在不访问每个传感器的数据库的情况下进行单个查询来找到它们?
    猜你喜欢
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    相关资源
    最近更新 更多