0

在 Rails 3.2 中说我有 3 个模型:Athlete、Event 和 Country

Class Athlete
  has_many :events
  has_many :countries, through: :event
end

Class Event
  belongs_to :athlete, counter_cache: true
  belongs_to :country, counter_cache: true
end

Class Country
  has_many :events
  has_many :Athletes, through: :event
end

因此,我现在可以轻松地生成一个按照他们参加的赛事数量排序的运动员数组。

scope :ranked, :order => 'athletes.events_count DESC' 

但是,如果我需要一组在特定国家/地区参加过比赛的运动员,并按他们在该国家/地区的比赛次数排序,该怎么办。

#country
def show
  @country.find(params[:id])
  @athletes_leaderboard = Athlete.includes(:events).where(id: @country.events.uniq.map(&:athlete_id)).ranked
end

给我一份在那个国家/地区参加过比赛的运动员的唯一列表,但它是按他们的事件数排名的,而不是按他们国家/地区的事件数。

我怎样才能按他们的国家事件计数排序,同时保持数据库性能。

4

1 回答 1

0

该查询涉及与子查询的位连接。

country_id = params[:id]
subsql = Event.select("events.athlete_id AS a_id, count(events.id) AS country_event_count").where("events.country_id = ?", country_id).group("a_id").to_sql
@athletes_leaderboard = Athlete.joins("JOIN (#{subsql}) AS participated_events ON participated_events.a_id = athletes.id").
  order("participated_events.country_event_count DESC")

的结果@athletes_leaderboard不再ActiveRecord::Relation。它是数据库结果行。您将需要遍历结果并将其呈现在您的视图中。例如(使用 HAML):

- @athletes_leaderboard.each do |athlete_data|
  = link_to athlete_data["name"], athlete_path(athlete_data["id"])

您可能希望将排行榜缓存在内存存储(如 Memcache)中,这样数据库就不会经常受到攻击。

于 2013-05-26T04:03:40.213 回答