在Rails 3.2中说我有3个模特:运动员,赛事和国家
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
为我提供了一个在该国家/地区进行了比赛的运动员的唯一列表,但是按照总事件计数排名,而不是按国家/地区的事件计数进行排名。
如何在保持数据库性能的同时按国家/地区事件计数进行排序。
答案 0 :(得分: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)中,以便数据库不会经常受到攻击。