【问题标题】:Multiple LIKE and AND operators in RAILS/POSTGRESQLRAILS/POSTGRESQL 中的多个 LIKE 和 AND 运算符
【发布时间】:2017-02-08 21:41:32
【问题描述】:

我使用 Rails 5.0.1 和 Postgresql 作为我的数据库。我有一个表,其中包含 :content 列,其中包含单词。

问题:当我在寻找一个特定的词时,我想看看这个词是否包含我选择的字母(字符)。假设我想 DB 返回包含字母“a”、“b”和“c”的单词(所有这些,但没有特定顺序)

我在做什么:我发现我可以使用 Word.where("content like ?", "%a%").where("content like ?", "%b%").where("content like ?", "%c%") 或者 Word.where("content like ? content like ? content like ?", "%a%", "%b%", "%c%") 在这两种情况下,即使我切换给定字母/子字符串的顺序,它也可以正常工作,例如。两者都会找到单词“back”、“cab”等。

问题:有没有更好/更DRY的方法?如果要查找包含 8 个不同字母的单词怎么办?我必须使用“内容喜欢吗?” 8次?是否可以将参数作为数组传递? (假设我不知道用户会输入多少个字母)

【问题讨论】:

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


    【解决方案1】:

    PostgreSQL 有一个方便的 expr op all (array) 表达式,因此您可以这样说:

    where content like all (array['%a%', '%b%', '%c'])
    

    作为以下形式的缩写:

    where content like '%a%'
      and content like '%b%'
      and content like '%c%'
    

    此外,如果您将 Ruby 数组交给 ActiveRecord,它将方便地将 ? 占位符替换为逗号分隔的列表。这让你可以说:

    Word.where('content like all (array[?])', %w[a b c].map { |c| "%#{c}%" })
    

    和:

    Word.where('content like all (array[?])', some_other_array.map { |c| "%#{c}%" })
    

    【讨论】:

    • 感谢您的出色回答!我也尝试使用 SIMILAR TO,但速度非常慢。这正是我想要的
    • 也有一些indexing options可以和LIKE一起使用。
    【解决方案2】:

    我找到了解决办法:

    letters = ["%a%", "%b%", "%c%"]
    Word.where((['content LIKE ?'] * letters.size).join(' AND '), *letters)
    

    这很简单,而且比我以前使用的要好得多。

    【讨论】:

      【解决方案3】:

      我认为SIMILAR TO 运算符可能会有所帮助。它允许您传入一个可以动态构建的正则表达式。

      letters = ['a', 'b', 'c']
      pattern = "%(#{letters.join('|')})%"
      Word.where("content SIMILAR TO ?", pattern)
      

      【讨论】:

      • 这种模式没有使用所有的字母。它使用一个,或两个,或全部,或第一个和第五个等。我想使用所有给定的字母,但不是以任何特定的顺序
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-19
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-12
      相关资源
      最近更新 更多