如何仅通过一次数据库调用多次调用范围

How to call a scope multipile times with just one database call

我有一个带有 Product 的数据库,并且产品有一个 name 属性,我想搜索它。我正在使用示波器来做到这一点:

scope name_contains, lambda{|q| where("name LIKE ?", "%#{q}%")}

当我搜索 "Awesome Product" 并且产品名为 "A pretty Awesome Product" 时效果很好,但当我搜索 "product awesome" 时效果不佳,因为单词的方向错误。我接下来尝试的是按 space 拆分查询并为每个单词调用范围:

def self.search(q)
  q.split(" ").map(&:strip).select{|x| !x.empty? }.each_with_index do |word,index|
    if index == 0
      data = Product.name_contains(word)
    else
      data = data.name_contains(word)
    end
  end
  data
end

这行得通,但它会为每个单词访问数据库。但我知道 rails 可以更好地处理这个问题,因为:

Product.name_contains("awesome").name_contains("product")

只访问数据库一次。这就是我想要的,但在迭代中调用name_contains方法时无法实现。

类似

words.inject(Product.all) {|scope, word| scope.name_contains(word)}

应该可以解决问题。在 rails 4 之前,您需要 Product.scoped 而不是 Product.all

请注意,这将需要完整的 table 扫描(除非您有其他要应用的条件)- mysql 将无法为此查询使用任何索引