型号:
我们假设,条目上有名称和金额。 如果我有一个视图需要显示特定用户的特定月份(让我们现在采用created_at),并希望显示一个表格,其中包含按类别分组的特定月份中的所有条目(不显示空类别)和一个总和并计算一个类别中的条目。
我的问题是: 查询数据库(并充分利用缓存)的最有效方法是什么?该视图将经常呈现,并且每次用户创建新条目时,自然地,一个类别的总和会改变,而不会改变其他类别的总和。
答案 0 :(得分:2)
查询部分可以通过范围完成:
class Category
scope :grouped_entries, lambda { |user, date|
select(['categories.*', 'COUNT(entries.id) as count_entries'])
.joins(:entries)
.where('entries.user_id = ?', user.id)
.where('MONTH(entries.created_at) = ?', date.month)
.group('categories.id')
}
end
然后可以循环:
<% Category.grouped_entries(current_user, Date.today).each do |category| %>
<%= category.name %> with <%= category.count_entries %> entries this month.
<% end %>
当然,缓存此操作需要您在本月创建条目时随时刷新缓存。例如,您可以像这样缓存查询:
@categories = Rails.cache.fetch("/grouped_entries/#{current_user.id}/#{Date.today.month}") do
Category.grouped_entries(current_user, Date.today).all
end
然后在使用user_id和条目created_at month创建新条目时简单地过期。我会说,在尝试单独缓存每个类别的条目之前,应首先使用此方法。此查询应该很快执行,因此您不必深入研究单独缓存每一行。它还将执行单个查询,而不是每个类别一个查询。
这就是为什么我不会单独缓存每一行:
答案 1 :(得分:1)
scope :grouped_entries, lambda { |user, date|
select(['categories.*', 'COUNT(entries.id) as count_entries']).
joins(:entries).
where('entries.user_id = ?', user.id).
where(':first_day <= entries.created_at AND entries.created_at <= :last_day', {
:first_day => date.at_beginning_of_month,
:last_day => date.at_end_of_month
} ).
group('categories.id')
}