(rails) Порядок по количеству лайков на веб-сайте

#ruby-on-rails #views #models

#ruby-on-rails #Вид #Модели

Вопрос:

У меня есть модель под названием websites that has_many :likes и, конечно, другая модель под названием likes with belongs_to :website . Я хочу получить массив всех веб-сайтов, но упорядочить их по количеству лайков, которые есть на веб-сайте.

полезная информация:

Я настроил его так, что @website.likes он будет возвращать лайки с @website . ( @website.likes.count — количество лайков на веб-сайте)

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

Комментарии:

1. sort не выполняет это с помощью SQL IIRC

2. Это может быть приемлемо, если количество сайтов в @popularwebsites невелико. Но если вы сначала соберете все веб-сайты в этот массив, а затем выполните сортировку на лету, это станет дорогостоящим и быстрым. Кроме того, это страдает от так называемой проблемы с запросом N 1, поскольку x.likes.count должен выполнить запрос к базе данных.

Ответ №1:

Как уже писали другие, вы можете выполнить объединение на likes , а затем упорядочить по количеству. Производительность может быть немного сомнительной в зависимости от индексации и т.д. У вас будет немного другой синтаксис в зависимости от того, используете ли вы Rails 2 или 3.

Альтернативой было бы поддерживать денормализованный likes_count столбец на websites , который обновляется при сохранении Like объекта модели.

Затем вам просто нужно сделать запрос на Website и указать порядок likes_count по убыванию (и он легко индексируется).

Для этого создайте likes_count целочисленный столбец на websites и укажите :counter_cache параметр в belongs_to объявлении в Likes модели. например:

 class Likes
  belongs_to :website, :counter_cache => true
end
  

Проверьте http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html для получения дополнительной информации

Комментарии:

1. Быстро и просто! Спасибо! (Я так понимаю, что ответ всех остальных тоже сработал!)

2. Классное решение! Недостатком этого является то, что, скажем, если вы удалите лайк из консоли db, удаление не отразится на like_count. В данном случае это не предложение о ставке, но о чем-то, о чем следует знать.

3. @randomguy правильный. Этот метод денормализации основан на создании / уничтожении Like объектов, которые должны выполняться с помощью Ruby, и позволяет обратным вызовам ActiveRecord позаботиться о домашнем хозяйстве. Если вы делаете это вне кода своего приложения, то вам нужно выполнить эту уборку самостоятельно, иначе ваши денормализованные данные перейдут в недопустимое состояние.

Ответ №2:

Этот запрос должен дать вам то, что вам нужно:

 all(:select => 'websites.*, count(*) as count',
  :joins => :likes,
  :group => :websites,
  :order => 'count DESC')
  

Комментарии:

1. это не вернет веб-сайты без лайков, потому что внутренние объединения удаляют все веб-сайты, у которых нет лайков, из результирующего набора.

Ответ №3:

Что-то вроде:

 SELECT Websites.*, COUNT(Like.ID) AS Liked
FROM websites
    LEFT OUTER JOIN Like ON websites.ID = Like.website_id
GROUP BY Like.website_id ORDER BY Liked DESC