如何仅通过一次数据库调用多次调用范围
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 将无法为此查询使用任何索引
我有一个带有 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 将无法为此查询使用任何索引