使用datamapper指定结果的顺序

时间:2012-03-09 22:12:05

标签: ruby associations datamapper

我有两个关联的模型。我有一个艺术家模型和一个评论模型。

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

我的目标是检索按照与之关联的评价的平均评分排序的艺术家数组。我不确定是否有任何一行解决方案,但我目前的方法是创建一个数组,其中艺术家的ID按平均评分排序。我如何获得这个数组的细节对于这个问题并不重要,但是让我说我​​现在有一个数组。

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

然后我检索艺术家。

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

问题是datamapper按以下顺序排序:除非您指定其他选项。因此,在我努力获得ids_sorted_by_rating之后,我仍然留下了一个按以下方式排序的艺术家列表:id。

任何能够根据相关评论的平均评分排序的艺术家列表的解决方案将非常受欢迎。如果我不需要数百万次访问数据库以获得该列表,则可获得奖励积分。 :)

谢谢,如果您需要更多信息,请询问,我会提供!

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

如果您只想显示数据(例如,您正在创建包含列表的网页),并且不会更改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方言,并且可能需要调整它以适用于你正在使用的任何DBMS(这适用于Sqlite,我还没有尝试过任何其他方法)。

然而,数组将按照每位艺术家评论的平均评分顺序排列。