优化ActiveRecord查询

时间:2015-11-25 11:57:11

标签: sql ruby-on-rails postgresql activerecord query-optimization

我有以下型号,并希望获得特定用户所有可用的帖子。

发布模型:

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查询?

3 个答案:

答案 0 :(得分:2)

这可以通过以下方式实现:

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

答案 1 :(得分:1)

这可以做到,我想:

Dictionary

您也可以在没有SQL字符串的情况下执行此操作,如下所示:

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

但我发现这样的结构导致参数绑定问题。我很确定这是一个错误,但我不确定这个技巧是否在公共ActiveRecord API中(ActiveRecord / Arel也是如此)。

答案 2 :(得分:-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)