如何有效地订购预先加载的记录?

时间:2015-05-11 17:48:39

标签: sql ruby-on-rails ruby postgresql

我有一个模型播放列表和一个模型用户,它们彼此相互拥有,通过连接模型PlaylistUser。

在我的播放列表#show action上,我想要打印所有播放列表用户的列表,以及与每个用户相关联的前两个播放列表(按照:song_count排序)。为了使这个只有一个查询,我急切地将播放列表表与用户一起加载。

现在我在拥有的东西:

播放列表/ show.html.erb

<% @playlist = Playlist.find(params[:id]) %>
<% @playlist_users = @playlist.users.includes(:playlists)
<% @playlist_users.each do |user| %>
  <%= user.name %>
  <%= user.playlists.order(:song_count).reverse.first.name %>
  <%= user.playlists.order(:song_count).reverse.second.name %>
<% end %>

模型

class User < ActiveRecord::Base
  has_many :playlist_users
  has_many :playlists, :through => :playlist_users
end

class PlaylistUser < ActiveRecord::Base
  belongs_to :playlist
  belongs_to :user
end

class Playlist < ActiveRecord::Base
  has_many :playlist_users
  has_many :users, :through => :playlist_users
end

当我删除排序时,查询非常快。但是通过排序,它非常慢,因为数据库显然必须先查询每个播放列表才能订购它们。

我可以在原始查询中订购播放列表吗?

1 个答案:

答案 0 :(得分:2)

实际上当你这样做时:

user.playlists.order(:song_count).reverse

您不利用eagerload,每次都重做查询。

感谢eagerloading你在内存中拥有了这个集合,所以你可以使用像sort这样的ruby方法对它进行排序:

user.playlists.sort_by {|pl| -pl.song_count }