如何按has_many关系中的对象数对Rails AR.find进行排序

Sam*_*der 10 activerecord ruby-on-rails

如何编写AR查找查询以使结果按has_many关联中的记录数排序?

class User < ActiveRecord::Base
  has_many :photos
end
Run Code Online (Sandbox Code Playgroud)

我想做点什么......

User.find(:all, :order => photos.count)
Run Code Online (Sandbox Code Playgroud)

我发现我的发现不是有效的代码.说我有以下数据.

User 1, which has 3 photos 
User 2, which has 5 photos 
User 3, which has 2 photos 
Run Code Online (Sandbox Code Playgroud)

我希望我的发现能够按照...的顺序将用户带回来

User 2, 
User 1, 
User 3 
Run Code Online (Sandbox Code Playgroud)

根据用户照片的数量

Ben*_*use 19

实现此目的的最简单方法可能是向该模型添加计数器缓存,然后按该列排序.

class Photo < ActiveRecord::Base
  belongs_to :user, :counter_cache => true
end
Run Code Online (Sandbox Code Playgroud)

并确保在您的users表中添加一个名为的列photos_count.

那你就能......

User.find(:all, :order => 'photos_count')
Run Code Online (Sandbox Code Playgroud)


Fra*_*eil 13

如果您不想要额外的列,则可以始终在返回的结果集中请求额外的列:

User.all(:select => "#{User.table_name}.*, COUNT(#{Photo.table_name}.id) number_of_photos",
         :joins => :photos,
         :order => "number_of_photos")
Run Code Online (Sandbox Code Playgroud)

这会生成以下SQL:

SELECT users.*, COUNT(photos.id) number_of_photos
FROM `users` INNER JOIN `photos` ON photos.user_id = users.id
ORDER BY number_of_photos
Run Code Online (Sandbox Code Playgroud)


Ste*_*sen 7

如果您不想添加计数器缓存列,则唯一的选择是在查找后进行排序.如果您:include在查找中使用了关联,则不会产生任何其他数据库工作.

users = User.find(:all, :include => :photos).sort_by { |u| -u.photos.size }
Run Code Online (Sandbox Code Playgroud)

注意sort_by块中的负号以从高到低排序.


Chu*_*ckE 5

我建议你不要编写直接SQL,因为它的实现可能因商店而异.幸运的是,你有bel:

User.joins(:photos).group(Photo.arel_table[:user_id]).
     order(Photo.arel_table[:user_id].count)
Run Code Online (Sandbox Code Playgroud)