按周/月等分组和ActiveRecord有关吗?

43

我正在对我的产品进行一些统计计算。用户执行了许多操作,比如发表评论。我想要展示他们过去一个月每周或者过去一年每月发布的评论数量。

使用activerecord有没有办法进行分组?还是我的最佳选择只能手动实现 - 根据自己的条件迭代记录并进行总结?

class User < ActiveRecord::Base
  has_many :comments
end

class Comments < ActiveRecord::Base
  belongs_to :user
end

@user.comments(:all).map {|c| ...do my calculations here...}

还有更好的方法吗?

谢谢! Oren

7个回答

96

4
比使用 Ruby 可枚举的 group_by() 快得多! - Will Nathan
Wojtek,如果一个月内没有创建任何东西呢?那么你将一无所获。 - Matt Smith
1
@MattSmith 我相信是这样的。幸运的是,从此查询的输出中读取值时提供默认值很容易:output.fetch("2012-08-01 00:00:00", 0) - Wojtek Kruszewski
在我的情况下,键是 Ruby 的 Time 对象,因此我可以通过 result[Time.current.utc.beginning_of_month] 访问结果。不确定为什么答案显示带有字符串键的结果,或者这是否随着时间改变过了。 - stephen.hanson
有排序吗?哈哈,键是无序的。 - Arian Faurtosh

32
在这种情况下,最适合我的解决方案是要么在SQL中直接操作,要么使用Ruby的group_by函数:
@user.all.group_by{ |u| u.created_at.beginning_of_month }

16
group_by 不是 ActiveRecord 的方法,而是 Ruby 中 Enumerable 模块的方法。 - Laurens
仅使用 u.created_at.month 更短。 - s.krueger
22
请注意,这将从数据库加载所有记录,实例化ActiveRecord对象,将日期解析为ActiveSupport的时区感知对象 - 这些都只是为了计算记录数。 - Wojtek Kruszewski
2
这是一个不好的做法,因为当你使用.all时,它会获取数据库中的所有记录,这将给你带来很大的开销。 - Ahmad Hussain
2
多浪费内存啊!使用@WojtekKruszewski的解决方案:@user.comments.group("DATE_TRUNC('month', created_at)").count - webaholik
显示剩余3条评论

27
这是更精细的版本。
@user.comments.group("year(created_at)").group("month(created_at)").count

另外

@user.comments.group("year(created_at)", "month(created_at)").count

14

我猜可能是这样:

@user.comments.count(:group => "year(created_at),month(created_at)")

干巴巴的代码,可能因人而异


我相信这也会按月份跨年分组 - 所以如果您有两年的数据,所有一月份的数据都会包括在第1年和第2年中。我要找的是一种方法,可以告诉我在一个24个月的窗口期内,每个月有多少个。 - teich
你可以添加一个条件来限制年份,例如:conditions => [:created_at, "> #{24.months.ago}"]。再次说明,未经测试,但应该可以使用类似这样的东西实现。 - Mike Tunnicliffe
4
这似乎是特定于MySQL的。 - Tachyons

4
使用 group_by
@user.comments.group_by(&:week)

class User < ActiveRecord::Base
  def week
    some_attribute_like_date.strftime('%Y-%W')
  end
end

这将为您提供一个按 YYYY-WW 格式分组的列表。

2

看看group date gem吧

https://github.com/ankane/groupdate

它有最新的提交,适用于postgresql,可以轻松地与chart kick集成以快速绘制图表,并支持时区!!


GroupDate 只能使用 UTC,因此如果您在数据库中使用其他时区,请考虑替代方案。 - msdundar

2

请查看has_activity插件。


谢谢指针。看起来 has_activity 只适用于 MySQL。我的生产主机是 PostgreSQL。 - teich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接