1

我有一个模型Link——它有很多热门。我正在尝试做的是从数据库表中聚合每小时点击次数的数据hits- 包含yearmonthdayhour.

一切正常,但是当我运行下面的代码时,我最终对数据库进行了近 1,000 个查询,这似乎相当多。

#before iteration
@hits = @link.hits.group('year, month, day, hour')
  .order('year ASC, month ASC, day ASC, hour ASC')
  .select('year, month, day, hour, count(*) as hits')


#inside iteration

#Line breaks are included here for easy reading
hits_per_hour =
  @hits.where(
    :year => t.year, 
    :month => t.month,
    :day => t.day,
    :hour => t.hour
  ).map(&:hits).first || 0

t是一个Time自第一次点击收到链接后以 1 小时为步长进行迭代的对象。

我认为 rails 会存储查询结果,而不是每次都重新查询。我也找不到任何有关缓存查询结果或任何内容的信息。我只是完全错过了一些东西,还是这真的是最简单的方法?

这是查询的示例(这是我在日志中看到的以一千块为单位的内容):

SELECT year, month, day, hour, count(*) as hits
FROM `hits`
WHERE
  `hits`.`link_id` = 1 AND
  `hits`.`year` = 2012 AND
  `hits`.`month` = 11 AND
  `hits`.`day` = 2 AND
  `hits`.`hour` = 14
GROUP BY year, month, day, hour
ORDER BY year ASC, month ASC, day ASC, hour ASC
4

1 回答 1

3

行。所以@hits将是一个 ActiveRecord::Relation 对象——本质上是一个 SQL 查询。我相信,因为每次迭代.where都使用不同的参数调用它,从而改变了查询,Rails 决定必须每小时重新运行一次查询。

最简单的解决方法可能是在迭代之前将 Relation '折叠'到一个数组中,然后每次使用纯 Ruby 来选择你想要的结果:

@hits = @link.hits.group('year, month, day, hour')
  .order('year ASC, month ASC, day ASC, hour ASC')
  .select('year, month, day, hour, count(*) as hits').all

进而:

hits_per_hour = (@hits.select{|record| record.year == t.year && record.month == t.month && record.day == t.day && record.hour == t.hour}.map(&:hits).first || 0)

不过,我认为这实际上可能不是最好的解决方案。根据您需要的数据以及您正在使用的数据,您应该能够在数据库中完成所有工作。

于 2012-11-02T19:42:33.783 回答