问题描述
||
我有两个模型
User
和Brand
,并且它们之间有多对多关系(通过UserBrand
表)。我有大约一千个用户,一千个品牌和每个用户一百个喜欢的品牌。
User.all.count # => 1000
Brand.all.count # => 1000
User.find(1).brands # => 100
如果我想找到5个用户,这些用户最喜欢的品牌几乎等于当前用户,那么我在用户模型中写下了以下内容
class User < ActiveRecord::Base
has_many :user_brands
has_many :brands,:through => :user_brands
def similar_users
result = {}
User.all.each do |u|
result[u] = shared_brands_with u.brands
end
result.sort{ |a,b| b[1] <=> a[1] }[1..5].map!{ |e| e[0] }
end
def shared_brands_with(brands)
(brands & @brands).size
end
end
以及ѭ5视图中的以下内容
<h2>Similar users</h2>
<ul>
<% @user.similar_users.each do |user| %>
<li><%= link_to user.name,user %></li>
<% end %>
</ul>
但是,在浏览器中查看用户推荐大约需要30-60秒。
所以我的问题是“如何加快建议的计算速度?”
UPD:使用
User.includes(:brands).each do |u|
result[u] = shared_brands_with u.brands
end
效果翻倍,但即使使用50个品牌(而不是100个品牌),在10秒内给出推荐的速度也很慢。
解决方法
因此,基本上。您正在拉动整个用户表。对于每个用户,获取该用户的品牌列表,大概是品牌本身。和过滤。我不会期望它很快。 :-)
您将需要在SQL中重写该逻辑以使其快速运行。抱歉,我的流利程度不比红宝石流利-不能真正理解标准……但是,实质上,可以通过单个查询来获取品牌。
它将变得又大又丑,充满了连接和in(),并可能包含by / having子句,但是它将比您当前的方法快。