多态ActiveRecord查询问题

时间:2016-05-31 19:19:41

标签: ruby-on-rails ruby-on-rails-4 activerecord polymorphic-associations

我有三个具有以下关联的模型:

User has_many :owns, has_many :owned_books, :through => :owns, source: :book
Book has_many :owns
Own  belongs_to :user, :counter_cache => true, belongs_to :book

我还有一个页面,通过以下查询跟踪拥有的顶级用户:

User.all.order('owns_count desc').limit(25)

我现在想添加一个新页面,该页面可以按照上面的拥有情况跟踪热门用户,但条件为:

Book.where(:publisher => "Publisher #1")

最有效的方法是什么?

1 个答案:

答案 0 :(得分:1)

如果这种情况有特别的东西,我很有意思,但我的镜头将是以下内容。

首先,我不知道如何在这里应用多态关联。您只有一本书可以属于该对象(用户)。据我所知,多态是将书连接到几个dif。对象(例如用户,图书馆,书架等)(编辑 - 问题的初始文本提到多态关联,现在它没有'

其次,我不相信有一种方法可以在这里缓存计数器,只要"发布者#1"是一个变化的输入参数,而不是一组预定义和已知的发布者(少数常量)。

第三,我认为单一出版商的书籍数量相对有限。因此,即使您的表中有数百万本书,每个出版商的书籍数量也应该达到数百本。

然后,您可以先查询所有发布商的图书ID,例如

book_ids = Book.where(:publisher => "Publisher #1").pluck(:id)

然后在拥有表中查询最高用户ID:

Owns.select("user_id, book_id, count(book_id) as total_owns").where(book_id: book_ids).group(:user_id).order(total_owns: :desc).limit(25)

免责声明 - 我没有在rails控制台中尝试使用该语句,因为我没有定义您的对象。我基于ActiveRecord中的群组通话docs

修改即可。为了提高效率,您可以尝试以下方法:

0)以防万一,确保Owns表上有两个外键的索引。

1)对第二个查询使用pluck以及不创建Own对象,尽管由于limit(25)而不应该有很大的区别。像这样:

users_ids = Owns.where(book_id: book_ids).group(:user_id).order("count(*) DESC").limit(25).pluck("user_id")

请参阅this question以供参考。

2)在一个后续查询中加载所有结果用户,而不是为每个用户加载N个查询

top_users = User.where(:id => users_ids)

3)尝试按第一顺序加入User表:

owns_res = Owns.includes(:user).select("user_id, book_id, count(book_id) as total_owns").where(book_id: book_ids).group(:user_id).order("total_owns DESC").limit(25)

然后使用owns_res.first.user