我有两个模型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
以及users/show
视图中的以下内容
<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秒内提供推荐也非常缓慢。
答案 0 :(得分:0)
所以,基本上。你正在拉动整个用户表。对于每个人,抓住该用户的品牌列表,大概是品牌本身。并过滤。我不会认为它很快。 : - )
您需要在SQL中重写该逻辑以使其快速。对不起,我不会比红宝石更流畅 - 不能真正理解标准......但实质上,通过一个查询获取品牌。
它会变得庞大而丑陋,充满了联接和()以及可能分组/有条款,但它会比你当前的方法更快。