我正在制作instagram复制副本。我想进行一次查询,以获取所有喜欢该帖子的用户。总而言之,一个用户有很多帖子,一个帖子有很多喜欢,并且用户也有很多喜欢。这些是我想出的解决方案
def get_user_likes
post = Post.find(params[:post_id])
#first solution
@user_likes = post.likes.map(&:users)
#second solution
@user_likes = User.includes(:likes).select(:username, :id, :profile_image).where(
likes: {post_id: params[:post_id])})
end
我也只想选择几列(第一个选项不允许我)。在性能方面,哪个选项更好?有更好的选择吗?
谢谢!
答案 0 :(得分:1)
就像Mehmet所说的那样,第二种解决方案更好。 我将扩展一下注释,第一个解决方案很容易理解,但是会针对地图中的每个类似对象调用一个查询,这些问题通常称为n + 1查询。
第二种解决方案更好,但是并不是您想要的。包含将运行第二个查询,并且以后可以迭代对象。
最好的解决方案是使用联接,首先是因为它将减少一个查询,其次是因为它将完全返回您的查询,因此只需将您的包含替换为联接,就可以了:
def user_likes
@user_likes = User.joins(:likes).select(:username, :id, :profile_image).where(likes: {post_id: params[:post_id])})
end
我可以进行更多探索,但答案将是博客文章,我可以为您推荐博客文章: https://semaphoreci.com/blog/2017/08/09/faster-rails-eliminating-n-plus-one-queries.html