DataMapper:按关联计数(相关对象的数量)对结果进行排序

时间:2013-12-09 14:24:00

标签: sql ruby associations datamapper ruby-datamapper

鉴于是m:n关系中的电影和演员。我想要做的是检索一个演员列表,按他们演奏的电影数量排序。

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 ]

我发现了另一个关于按关联的单个属性进行排序的问题,但这种方法仅适用于真实属性。任何有用的解决方案都会有所帮THX!

2 个答案:

答案 0 :(得分:2)

以Sean Larkin的答案为出发点,我得到了类似的结论:

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>
]

答案 1 :(得分:0)

DataMapper的文档很少过时,我努力尝试完成你正在做的事情。

我改为使用直接MySQL查询:

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

重要的是要注意,当您使用直接MySQL查询时,返回结构而不仅仅是数据的哈希值。如果您将此数据作为JSON返回,则必须手动将其转换为哈希值。

您可以通过以下方式将结构转换为Ruby 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)