繁体   English   中英

通过语句通过ActiveRecord和带有has_many的Postgres对结果进行排序

[英]Ordering results with ActiveRecord and Postgres with has_many through statement

我在这里有以下3个模型:

class User < ActiveRecord::Base
  has_many :parties, foreign_key: 'organizer_id'

  has_many :invitations, foreign_key: 'attendee_id'
end

class Party < ActiveRecord::Base
  belongs_to :organizer, class_name: 'User'

    has_many :invitations
    has_many :attendees, through: :invitations
end

class Invitation < ActiveRecord::Base
  belongs_to :party
  belongs_to :attendee, class_name: 'User'
  belongs_to :inviter, class_name: 'User'
end

我想让一个特定聚会的所有参与者都可以按邀请最多的人进行排序。

我该怎么做呢?

谢谢你的帮助。

几个可能的解决方案:

肮脏的一

party.attendees.joins(:invitations).select('parties.*', 'COUNT(DISTINCT invitations.id) as invitation_count').group('parties.id').order('invitation_count')

优点:可能有效

缺点:这很丑陋,无法解释自身,您最终将很难查询关系。 宁可避免。

稍微干净一点

在应用程序级别对其进行排序:

party.attendees.includes(:invitations).sort_by {|att| att.inivtaions.to_a.size }

优点:更清楚您在做什么

缺点:返回不可查询数组,而不是关系。 仍然需要解释为什么要调用to_a (以避免N + 1问题)。

最干净的

添加一个额外的列invitations_count给与会者表,并添加counter_cache: truebelongs_to :attendee在你的邀请模式。 利润!

party.attendees.order(:invitations_count)

优点:不错,不言自明。 无需从数据库加载邀请。 容易查询的关联。

缺点:在开始使用它之前,您需要更新所有记录的counter_cache:

Attendees.includes(:invitations).each { |att| att.invitation_count = att.invitation.to_a.size }

之后,Rails将负责使列与与参加者邀请相关联的许多列保持同步。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM