我有一个产品,用户和product_click模型。
在product_click中,我有一个count
列,我在其中记录,哪个用户点击哪个产品多少次。
我尝试过
Product.sort_by{ |r| r.product_clicks.where(user_id: user.id).first.try(:count).to_i
给出期望的结果,但在运行时创建大量查询。
product_click.rb
belongs_to :product
belongs_to :user
product.rb
has_many :product_clicks, dependent: :destroy
user.rb
has_many :product_clicks, dependent: :destroy
模式
create_table "product_clicks", force: :cascade do |t|
t.bigint "product_id"
t.bigint "user_id"
t.bigint "count", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
在控制器中
Product.left_outer_joins(:product_clicks).order("count DESC NULLS LAST")
现在我正在寻找类似的东西。
但是在这里,我无法检查计数是否属于哪个特定用户。 如果我要添加
Product.left_outer_joins(:product_clicks).where(resource_clicks: { user_id: user.id }).order("count DESC NULLS LAST")
然后显示的是用户点击过的产品,而没有点击过的产品。
我也尝试过
Product.left_outer_joins(:product_clicks).where(product_clicks: { user_id: [user.id, nil] }).order("count DESC NULLS LAST")
但是给我我所单击的所有内容,而所有其他人都没有单击。如果有人点击了我没有点击的内容,那么它不会显示给我
答案 0 :(得分:0)
虽然我在考虑其他方式,但直接的方法是两步解决方案。
product_ids = ProductClick.where(user_id: user.id).order('count desc').pluck(:product_id)
products = Product.where(id: product_ids)
它肯定会改善您的时间,并且比您的查询(N + 1)要好。
使用预加载
Product.includes(:product_clicks).where('product_clicks.user_id' => user.id).order('product_clicks.count desc')
上面的查询也应该以相同的方式产生结果,但是无论如何它可能在内部命中2个查询。
使用Haveing子句-推荐
Product.includes(:product_clicks).having('product_clicks.user_id' => user.id).order('product_clicks.count desc')