N + 1查询具有动态搜索和急切加载

时间:2015-07-30 13:31:00

标签: ruby-on-rails postgresql ruby-on-rails-4 rails-activerecord

我有2个型号:

class User < ActiveRecord::Base
 has_many :friends, through: :friendships
 has_many :friendships, dependent: :destroy
end

class Friendship < ActiveRecord::Base
  belongs_to :user, class_name: 'User'
  belongs_to :friend, class_name: 'User'

end

我想要做的是使用.where("name LIKE ?", "%#{name}%")并搜索用户的朋友和朋友。

到目前为止,我有这样的事情:

second_level =[]
first_level =  user.friends.includes(:friends).where("name LIKE ?", "%#{name}%")
first_level.each { |u| second_level += u.friends.where("name LIKE ?", "%#{name}%") }

但这会导致N + 1查询出现问题,因为每个用户朋友都会在朋友中搜索一个新查询。

有没有办法用急切的加载来做到这一点? (关于这一点的有价值的文章是http://blog.arkency.com/2013/12/rails4-preloading/,但它没有解决2级深度的问题

以类似的方式,我有一个PORO收集用户朋友和朋友 - 朋友,工作正常。问题似乎是where条款。

2 个答案:

答案 0 :(得分:0)

first_level =  user.friends.includes(:friends).where("name LIKE ?", "%#{name}%")

在此之后你可以做到

second_level = User.joins(:friendships).where(friendships: { user_id: first_level.map(&:id) }).where("name LIKE ?", "%#{name}%")

答案 1 :(得分:0)

在我的特殊情况下,我希望用户只能在他的社交圈中按姓名搜索人。

这就是为什么我尝试通过首先找到与名称匹配的所有用户然后通过请求用户的完整网络而没有名称标准(这是方法,我在我的描述中提到过,它没有引起任何N + 1个查询)

最后,我的搜索方法如下所示:

    all_matches = User.where("name LIKE ?", "%#{name}%")
    network = UserNetwork.new(user: user)
    (all_matches & network.full).uniq