背景
我正在创建一个仪表板作为项目,我有一个查询,我认为这将是一个重大的性能问题:
<% for outlet in @outlets %>
<% if Monitoring.where(:outlet_id => outlet.id).where('date(created_at) = ?', Date.today).exists? %>
<li>
<a class="done" href="<%= outlet_url(outlet) %>" rel="tooltip" title="<%= outlet.name %>"></a>
</li>
<% else %>
<li>
<a href="<%= outlet_url(outlet) %>" rel="tooltip" title="<%= outlet.name %>"></a>
</li>
<% end %>
<% end %>
我想要实现的是页面上的一系列点。如果锚标记有一个已完成的类,它将显示为绿色,如果不是,它将显示为红色(通过CSS完成)。
除了这里明显的DRY问题之外,这个查询非常繁重,所以我正在研究改进它的方法。
每天至少监控一次插座( An Outlet has_many:监控)。对于每个插座,我需要检查是否在特定日期对其进行了监控,并相应地输出HTML。
如果有人能帮助我,那就太棒了。 (此外,任何有关缓存此建议的建议都将受到赞赏。)
提前干杯:)。
答案 0 :(得分:1)
您可以为当前监视器创建条件关联,然后使用includes来获取原始查询的关联当前监视。
class Outlet
has many :current_monitorings, :class_name => "Monitoring",
:conditions => proc { [ 'monitorings.created_at > ?', Time.now.midnight ] }
end
@outlets = Outlet.includes(:current_monitorings)
@outlets.each do |outlet|
if outlet.current_monitorings.empty?
# the no monitor today case
else
# it's been monitored today
end
end
在Postgres级别,您可能会受益于监控的索引(outlet_id,created_at),以支持#includes隐含的外部联接。
顺便说一下,在视图中执行数据库查询是不好的方式。将域逻辑放在模型中,让控制器执行查询并将结果提供给表示层。答案 1 :(得分:0)
也许试试:
<% @outlets.includes(:monitorings).each do |outlet| %>
<% css_class = outlet.monitorings.any? { |m| m.created_at == Date.today } ? 'done' : '' %>
<li><%= link_to '', outlet_url(outlet), :class => css_class, :rel => "tooltip", :title => outlet.name %></li>
<% end %>
它将执行1个大查询。
答案 2 :(得分:0)
缓存此方法的一个好方法是使用回调对数据库进行非规范化。在Outlet模型中,您可以添加一个名为last_monitored_on的字段;在保存监视器的任何时候,使用日期更新相应的Outlet模型。然后,您根本不必查询监视器。
您还可以考虑缓存该网页片段,并让它每天过期。