我需要从一个数组中进行where查询,其中数组的每个成员都是一个“相似”的AND运算。例:
SELECT ... WHERE property like '%something%' AND property like '%somethingelse%' AND ...
使用ActiveRecord where
函数很容易,但我不确定如何首先消毒它。我显然不能只创建一个字符串并将其填充到where
函数中,但似乎没有办法使用?
。
谢谢
构建LIKE模式的最简单方法是字符串插值:
where('property like ?', "%#{str}%")
如果你有一个数组中的所有字符串,那么你可以使用ActiveRecord的查询链和inject
来构建你的最终查询:
a = %w[your strings go here]
q = a.inject(YourModel) { |q, str| q.where('property like ?', "%#{str}%") }
然后你可以q.all
或q.limit(11)
或你需要做的任何事情来获得你的最终结果。
这是一个关于它是如何工作的快速教程;你应该检查Active Record Query Interface Guide和Enumerable
documentation。
如果你有两件事(a
和b
)匹配,你可以这样做:
q = Model.where('p like ?', "%#{a}%").where('p like ?', "%#{b}%")
where
方法返回一个支持所有常用查询方法的对象,因此您可以根据需要将调用链接为M.where(...).where(...)...
;其他查询方法(例如order
,limit
,...)返回相同类型的对象,因此您也可以将它们链接起来:
M.where(...).limit(11).where(...).order(...)
你有一系列喜欢的东西,你想将where
应用到模型类,然后将where
应用于返回的内容,然后再次使用你的数组。看起来像反馈循环的东西倾向于要求inject
(来自“map-reduce”成名的AKA reduce
):
注入(初始){|备忘录,obj | block}→obj
通过应用由块或命名方法或运算符的符号指定的二进制操作来组合枚举的所有元素。
如果指定一个块,那么对于枚举中的每个元素,块将传递一个累加器值(memo),而元素[...]结果将成为memo的新值。在迭代结束时,memo的最终值是方法的返回值。
所以inject
获取块的输出(在我们的例子中是where
的返回值)并将其作为输入提供给下一次执行块。如果你有一个阵列,你就可以使用inject
:
a = [1, 2, 3]
r = a.inject(init) { |memo, n| memo.m(n) }
然后就是这样:
r = init.m(1).m(2).m(3)
或者,在伪代码中:
r = init
for n in a
r = r.m(n)
如果你正在使用AR,做一些像Model.where(property: your_array)
或Model.where("property in (?)", your_array)
这样的方式,一切都被消毒了
假设您的数组是model_array,请尝试使用Array select:
model_array.select{|a|a.property=~/something/ and a.property=~/somethingelse/}
当然你可以随意使用任何正则表达式。