这可以重构为单个数据库调用吗?
我在 Events
模型中有一个事件列表。我需要做的是按城市/州对事件进行可视化分组。
从视觉上看,它看起来像这样:
这是我认为我正在做的事情的精简外观实现这一点:
<% @number.events.locations.each do |location| %>
<li>
<h4><%= "#{location.city}, #{location.state}" %></h4>
<ol>
<% @number.events.city_state(location).each do |event| %>
<li><%= event.status %></li>
<% end %>
</ol>
</li>
<% end %>
以及相应的范围:
scope :locations, :group => 'city, state'
scope :city_state, lambda {|location| {:conditions => ["city = ? AND state = ?", location.city, location.state] }}
但问题是我正在为每个位置进行额外的数据库调用。
那么我可以将其简化为单个查询吗?
I have a listing of events in an Events
model. What I need to do is visually group events by city/state.
Visually, that will look like this:
Here's, a stripped down look of what I'm doing in my view to make this happen:
<% @number.events.locations.each do |location| %>
<li>
<h4><%= "#{location.city}, #{location.state}" %></h4>
<ol>
<% @number.events.city_state(location).each do |event| %>
<li><%= event.status %></li>
<% end %>
</ol>
</li>
<% end %>
And the corresponding scopes:
scope :locations, :group => 'city, state'
scope :city_state, lambda {|location| {:conditions => ["city = ? AND state = ?", location.city, location.state] }}
The problem, though, is that I'm doing an additional database call for every location.
So can I get that down to a single query?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用预先加载从数据库中预取关联:
如果您一次提取所有事件,您可以将其更改为预加载事件的位置关联:
如果您需要某些其他对象的事件(例如您的
@number
对象),您可能希望在控制器中执行类似的操作,例如:现在,在此示例中,将从数据库中提取您的
@number
对象以及所有的事件和所有这些事件的地点。有关更多信息,请参阅 Rails 指南:http://guides.rubyonrails .org/active_record_querying.html#eager-loading-associations
更新了我在评论中的答案:
根本不使用范围,您可以简单地使用 Ruby 为您完成这项工作,并将 ActiveRecord 和额外的数据库调用从循环中剔除。
Enumerable#group_by
将根据您提供的某些属性获取集合和分组。在这种情况下,您可以获取所有事件,按城市和州进行分组,然后迭代它返回的哈希值:这样做可能比使用范围不太漂亮,但它允许您进行一次数据库调用,并且就这样吧。
Use eager loading to pre-fetch associations from your database:
If you're pulling all of your events at once, you could change it to pre-load the location associations for the events:
If you need events for some other object (like your
@number
object), you might want to do something like this in your controller, for example:Now, in this example, your
@number
object will be pulled from the database along with all of it's events and all of those events' locations.See the Rails guides for a little more info on this: http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
Updated with my answer from the comments:
Instead of using scopes, at all, you can simply use Ruby to do the work for you and cut ActiveRecord and extra database calls out of the loop.
Enumerable#group_by
will take a collection and group by some attribute you provide. In this case, you could take all of your Events, group by the city and state, and then iterate over the hash it returns:Doing this may be a little less pretty than using scopes, but it allows you to make one database call and leave it at that.
这是一个 O(n^2) 解决方案,假设您的
locations.each do |location|
循环按广告所示工作。应该将其降低至 2 分贝。尚未测试,稍后再回来查看。
Here's an O(n^2) solution, assuming your
locations.each do |location|
loop works as advertised. Should cut it down to 2 db hits.Not tested yet, will check back later.