3

我有以下模型,並且想要獲得特定用戶沒有在他們身上放置的所有可用帖子。優化ActiveRecord查詢

郵政型號:

class Post < ActiveRecord::Base 
    has_many :likes 
    has_many :users, through: :likes 

    scope :available, -> { where available: true } 
end 

就像型號:

class Like < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :user 
end 

用戶模型:

class User < ActiveRecord::Base 
    has_many :likes 
    has_many :posts, through: :likes 
end 

我想出了這樣的ActiveRecord查詢:

Post.available - Post.available.joins(:likes).where('likes.user_id = ?', user.id) 

有沒有一種優化的方式來實現這一目標?也許甚至是一個等效的SQL查詢?

+1

使Post.available.joins(:likes).where('likes.user_id =?',user.id)'作用域的範圍減去 –

回答

2

這可以通過以下方式實現:

Post.available.where("id not in (select post_id from likes where user_id = ?)", user.id) 
-2

試試這個: -

Post.available.joins(:likes).where('likes.user_id NOT IN (?)', user.id) 

或者你也可以在後期添加到模型範圍

class Post < ActiveRecord::Base 
    scope :no_user_likes, ->(id) { joins(:likes).where('likes.user_id NOT IN (?)', id) } 
end 

然後就可以調用,如: -

Post.available.no_user_likes(user.id) 
+0

與從(現在正確刪除)第一個答案相同的問題:這取得**每個人都喜歡的帖子,但這個用戶**。所以最終的結果是錯誤的。 –

1

這能做到這一點,我想:

Post.available.where('NOT EXISTS (?)', 
    user.likes.where('likes.post_id = posts.id') 
) 

你也可以做到這一點沒有SQL字符串可言,就像這樣:

Post.available.where(
    user.likes.where(post_id: Post.arel_table[:id]).exists.not 
) 

但我見過像這樣會導致問題的構建參數綁定。我很確定這是一個錯誤,但我不確定這個技巧是否在公共的ActiveRecord API中(ActiveRecord/Arel真的是這麼責怪)。