1

我有一个表达式,根据当前用户给他们的星数选择前三名评论

@event.reviews.sort_by { |r| -r.stars.select{ |s| s.user_id == current_user.id }.count }.first(3)

问题在于它将所有评论和星标都拉到内存中,并在 Ruby 中执行此操作。如果没有在直接 SQL 中执行此操作,有没有办法在 arel 中实现相同的操作,以便数据库完成大部分计算而不是 Ruby?

4

1 回答 1

1

可以用下面的,counter这里代表一个starsfromcurrent_user的个数review

# Single query with inner join
@event.reviews.joins(:stars)
       .select("reviews.*, stars.id ,SUM(stars.user_id = #{current_user.id}) AS counter ")
       .group("reviews.id ")
       .order("counter DESC").limit(3)

上面的 sql 查询将创建一个reviews和的内连接表stars

根据这些表的大小,预先加载reviewsstars获取@event. 例如

 # Eager loading with separate queries
 @event =  Event.find(params[:id]).includes(:reviews => :stars)

上述方法将进行一次查询以获取与事件相关的所有评论的所有星。

如果您在同一请求中的其他地方使用starsand reviews,那么最好使用includes.

于 2013-09-19T03:49:54.227 回答