【问题标题】:Creating a where query in rails from an array从数组中在 rails 中创建 where 查询
【发布时间】:2012-05-25 04:39:22
【问题描述】:

我需要从一个数组中进行 where 查询,其中数组的每个成员都是 AND 的“like”操作。示例:

SELECT ... WHERE property like '%something%' AND property like '%somethingelse%' AND ...

使用 ActiveRecord where 函数很容易,但我不确定如何首先对其进行清理。我显然不能只创建一个字符串并将其填充到where 函数中,但似乎没有办法使用?

谢谢

【问题讨论】:

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


    【解决方案1】:

    构建 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.allq.limit(11) 或任何您需要做的事情来获得最终结果。


    这里有一个关于其工​​作原理的快速教程;您还应该查看Active Record Query Interface GuideEnumerable documentation

    如果您有两件事(ab)要匹配,您可以这样做:

    q = Model.where('p like ?', "%#{a}%").where('p like ?', "%#{b}%")
    

    where 方法返回一个支持所有常用查询方法的对象,因此您可以根据需要将调用链接为M.where(...).where(...)...;其他查询方法(例如orderlimit、...)返回相同类型的对象,因此您也可以将它们链接起来:

    M.where(...).limit(11).where(...).order(...)
    

    您有一系列要 LIKE 的东西,并且您想将 where 应用于模型类,然后将 where 应用于返回的内容,然后再一次,直到您用完您的数组。看起来像反馈循环的东西往往需要inject(又名reduce,来自“map-reduce”名声):

    注入(初始){|备忘录,obj |块 } → obj

    通过应用二元运算组合枚举的所有元素,该二元运算由命名方法或运算符的块或符号指定。

    如果你指定了一个块,那么对于 enum 中的每个元素,块都会被传递一个累加器值(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)
    

    【讨论】:

    • 哇!这样可行!我是 Rails(和 ruby​​)的新手,你介意给我简单解释一下这里到底发生了什么吗?
    • @Mattieu:这有帮助吗?解释你一直使用的功能性东西可能很困难,通常会有一个“啊哈!”你得到它的那一刻,在那之前一切都是神奇的。
    • @Mattieu,如果您不怕添加宝石,请查看 squeel github.com/ernie/squeel。它有很棒的功能like_all/like_any: queries = %w[ruby rails].map{|s|"%#{s}%"}; Product.where{title.like_all queries}.
    • @muistooshort 哇非常感谢你,这是一个很好的解释!我没有意识到 where 方法(以及所有其他方法)可以被链接!与inject 一起使用创建查询非常有意义,非常聪明!非常感谢您的帮助!
    • @jdoe 代码库不是我的,但我会调查一下,谢谢!
    【解决方案2】:

    如果您使用的是 AR,请执行 Model.where(property: your_array)Model.where("property in (?)", your_array) 之类的操作,这样,一切都会被清理干净

    【讨论】:

    • 如果我错了,请纠正我,但这不会做一个“=”吗?我需要“点赞”
    • 你说得对,我想我在阅读问题时跳过了类似的部分
    【解决方案3】:

    假设你的数组是model_array,试试数组选择:

    model_array.select{|a|a.property=~/something/ and a.property=~/somethingelse/}
    

    当然,您可以随意使用任何正则表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多