2013-12-09 3 views
1

Представлены фильмы и актеры в соотношении m: n. То, что я хочу сделать, это получить список актеров, упорядоченный по количеству фильмов, которую они играли вDataMapper: Сортировка результатов по количеству ассоциаций (количество связанных объектов)

class Movie 
    include DataMapper::Resource 
    property :id,  Serial 
    property :title, String 
    has n, :actors, through: Resource 
end 

class Actor 
    include DataMapper::Resource 
    property :name, String, key: true 
    has n, :movies, through: Resource 
end 

В псевдо-DM, что я хочу это:.

Actor.all order: [ :movies.count ] 

Я нашел другой вопрос о сортировке по одному атрибуту ассоциации, но этот подход работал только для реальных свойств. Любое полезное решение было бы полезно. Спасибо!

ответ

2

Взятие ответ Шона Ларкина в качестве отправной точки у меня получилось примерно так:

actors = repository(:default).adapter.select(
    "SELECT actors.name, count(actor_movies.actor_name) AS count " + 
    "FROM actors " + 
    "JOIN actor_movies WHERE actors.name = actor_movies.actor_name " + 
    "GROUP BY actors.name " + 
    "ORDER BY count(actor_movies.actor_name) desc " + 
    "LIMIT 5;" 
) 

=> [ 
    #<struct name="Samuel L. Jackson", count=66>, 
    #<struct name="Michael Caine", count=64>, 
    #<struct name="Robert De Niro", count=59>, 
    #<struct name="Harvey Keitel", count=58>, 
    #<struct name="Gene Hackman", count=57> 
] 
+0

Если вы хотите вернуть хэш из этих данных так же просто, как: 'act = repository (: default) .adapter.select ( " SELECT players.name, count (actor_movies.actor_name) AS count "+ " ОТ актеров "+ "РЕГИСТРИРУЙТЕСЬ actor_movies ГДЕ actors.name = actor_movies.actor_name" + "GROUP BY actors.name" + " ORDER BY COUNT (actor_movies.actor_name) по убыванию" + "ПРЕДЕЛ 5;" ) .map {| структура | {: name => struct.name,: count => struct.count}} ' –

0

Документация для DataMapper немного устарела, и я изо всех сил пытался сделать то же, что и вы.

вместо этого я использовал прямой запрос MySQL:

records = repository(:default).adapter.select(“SELECT * FROM actor ORDER BY count(movies) desc;”) 

Важно отметить, что при использовании прямого запроса MySQL, что структура возвращается, а не только хеш данных. Вам придется преобразовать его в хэш вручную, если, скажем, вы возвращаете эти данные как JSON.

Вы можете преобразовать хэш-структуру, чтобы в Рубине 1.8-1.9 через:

actors = repository(:default).adapter.select("SELECT actors.name, count(actor_movies.actor_name) AS count " + "FROM actors " + "JOIN actor_movies WHERE actors.name = actor_movies.actor_name " + "GROUP BY actors.name " + "ORDER BY count(actor_movies.actor_name) desc " + "LIMIT 5;").map{|struct| {:name => struct.name, :count => struct.count}}

В Ruby 2.0, они добавили to_h так что вы можете использовать это:

actors = repository(:default).adapter.select("SELECT actors.name, count(actor_movies.actor_name) AS count " + "FROM actors " + "JOIN actor_movies WHERE actors.name = actor_movies.actor_name " + "GROUP BY actors.name " + "ORDER BY count(actor_movies.actor_name) desc " + "LIMIT 5;").map(&:to_h)