Указание порядка результатов с помощью datamapper - PullRequest
2 голосов
/ 10 марта 2012

У меня есть две модели, которые связаны.У меня есть модель Artist и модель Review.

class Artist
  include DataMapper::Resource

  property :id, Serial
  property :name, String

  has n, :reviews

end

class Review
  include DataMapper::Resource

  property :id, Serial
  property :rating, Integer
  property :body, String

  belongs_to :artist
end

Моя цель - получить массив художников, упорядоченных по среднему рейтингу отзывов, связанных с ними. Я не являюсьКонечно, есть ли однострочное решение, но мой текущий метод - создать массив с идентификаторами артистов, отсортированными по среднему рейтингу.Детали того, как я получаю этот массив, не важны для этого вопроса, но допустим, у меня теперь есть массив.

ids_sorted_by_rating = [4,5,23,9,2,48,17,....]

Затем я получаю художников.

artists = Artist.all(:id => ids_sorted_by_rating)

Проблема в том,этот datamapper упорядочивает по: id, если вы не укажете другую опцию.Так что после всей моей тяжелой работы, чтобы получить ids_sorted_by_rating, я все еще остаюсь со списком артистов, просто отсортированным по: id.

Любое решение, которое дает мне список художников, упорядоченных по среднему рейтингу соответствующих обзоров, будет НАМНОГО оценено.Бонусные баллы, если мне не нужно попадать в базу данных миллион раз, чтобы получить этот список.:)

Спасибо, и если вам нужна дополнительная информация, просто спросите, и я предоставлю!

Ответы [ 2 ]

1 голос
/ 10 марта 2012

AFAIK Нет простого способа сортировки по агрегации в DataMapper (способ сделать это одним запросом).Вы можете использовать переупорядочение результатов на стороне приложения (если ваши наборы данных не слишком велики для этого):

hash = artists.index_by(&:id)
# if you do not have index_by - use a artists.inject({}){|h,a| h.merge(a.id => a)} 
ids_sorted_by_rating.map{|id| hash[id]}
0 голосов
/ 10 марта 2012

Если вы просто хотите отобразить данные (например, создаете веб-страницу со списком) и не собираетесь изменять Artists, вы можете «обмануть» и использовать SQL (если вы используетехранилище данных SQL):

repository(:default).adapter.select(
'SELECT artists.*
FROM artists JOIN reviews on artists.id = reviews.artist_id
GROUP BY artists.id
ORDER BY AVG(reviews.rating)')

Это не возвращает Artist объектов, но массив Structs, каждый из которых будет иметь все свойства Artist, поэтому вы можете получить вседанные, но их обновление не принесет много пользы.Более поздний запрос может затем извлечь «реальный» Artist (например, пользователь нажимает на ссылку для художника, и вы можете использовать соответствующее значение id для запроса соответствующего Artist объекта).* Вам также нужно быть осторожным с различными диалектами SQL, и, возможно, потребуется настроить его для работы с любой используемой СУБД (это работает на Sqlite, я не пробовал другие).* Массив, однако, будет в порядке среднего рейтинга отзывов каждого художника.

...