2013-09-18 3 views
0

У меня есть выражение, которое выбирает тройку отзывов по количеству звезд, текущий пользователь дал имПреобразовать выражение Рубите AREL

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

Проблемы заключается в том, что он тянет все отзывы и звезда в память и делает это в Ruby. Если не сделать этого в прямом SQL, есть ли способ достичь такой же цели в isl, чтобы база данных выполняла большую часть вычислений вместо Ruby?

ответ

1

Вы можете использовать следующие, counter здесь представляет число stars от current_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.

В зависимости от размера этих таблиц может быть более оперативная загрузка reviews и stars для случая, когда вы выбираете @event. Напр.

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

Вышеуказанный метод сделает один запрос, чтобы получить все звезды для всех обзоров, связанных с событием.

Если вы используете и reviews в других местах, указанных в этом заявлении, то лучше всего скачать их с помощью includes.

Смежные вопросы