Want to sort by association records count in Datamapper
-
19-09-2019 - |
Question
Lets say I have the following DataMapper resources:
class Post
include DataMapper::Resource
has n, :comments
...
end
class Comment
include DataMapper::Resource
belongs_to :post
...
end
To get the ordered list of posts, I know you can do:
@posts = Posts.all(:order => :date.desc)
But lets say I want to display all the Posts ordered descending by how many comments they have. How would I do that?
Solution
A good way to do this for performance reasons is to cache the comment_count value for the post, which would then give you an attribute to use for the :order, maybe like :order => :comment_count_cache.desc . This is easily setup by adding an after creation hook for the Comment model.
OTHER TIPS
You can alternatively use sort_by, which calls a separate query:
@post = Post.all(:order => :date.desc).sort_by { |post| -post.comments.count }
If you want to change the order, you can take out the minus sign:
@post = Post.all(:order => :date.desc).sort_by { |post| post.comments.count }
This is nice syntactically, but like adamaig points out, it'll probably perform worse than caching the number of comments in the db because you are adding an additional SQL query.
I believe that the SQL you want to generate is:
SELECT posts.*, COUNT(comments.id) AS comments_count FROM posts
JOIN comments ON posts.id = comments.post_id
GROUP BY posts.id ORDER BY comments_count DESC
As far as I know, this isn't something you can do programmatically with the Query class. Just drop into SQL for this.