【问题标题】:How Do I Write A Query In Ruby Using Variables WIthin A Where Clause (PostgreSQL)如何在 Ruby 中使用 Where 子句 (PostgreSQL) 中的变量编写查询
【发布时间】:2012-12-17 23:39:12
【问题描述】:

这就是我希望在不使用 gem 的情况下实现的目标。我在我的一个视图中有一个搜索功能,我希望允许人们在单个字段中输入名字和姓氏,让我的类方法搜索名字和姓氏并生成一个列表。我目前有以下丑陋的代码,它将在两个字段上进行全文搜索。怜悯我 :) 我是 SQL 和 PostgreSQL 的新手。我只做了基本的查询。

  def self.text_search(query)
    if query.present?
      q1, q2, q3, q4 = query.split(' ')
      case
      when q4 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR first_name @@ :q3 OR first_name @@ :q4 OR last_name @@ :q1 OR last_name @@ :q2 OR last_name @@ :q3 OR last_name @@ :q4', q1: q1, q2: q2, q3: q3, q4: q4)
      when q3 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR first_name @@ :q3 OR last_name @@ :q1 OR last_name @@ :q2 OR last_name @@ :q3', q1: q1, q2: q2, q3: q3)
      when q2 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR last_name @@ :q1 OR last_name @@ :q2', q1: q1, q2: q2)
      else
        where('first_name @@ :q1 OR last_name @@ :q1', q1: q1)
      end
    else
      scoped
    end
  end

此代码适用于在两个字段中搜索整个单词并生成所有匹配的记录。但是,我想做的是能够搜索以在搜索框中输入的值开头的列。例如,如果有人输入“Pat”,则查询将选择 Pat、Patrick、Patrice、Patricia 等。我确信有更好的方法来编写我包含的代码,我可以在其中列出我想要的所有值检查 first_name 和 last_name(或者至少我希望有)。

我今天一直在做很多关于这个的网络搜索。我发现了很多关于这方面的各个方面的信息。我看到了如何使用变量创建正则表达式。这对我来说很明显。我的问题是弄清楚如何将这些信息传递到我的 where 子句中。例如,我为所有四个字段尝试了以下代码。

qr1 = /^#{q1}/

然后我做了一个类似的 where 子句,我检查了所有四个值的 first_name 和 last_name。我的查询没有返回任何行。

where ('first_name ~ :qr1', qr1: qr1)

我还看到了有关检查子字符串与数组进行比较的解决方案。我在该解决方案中看到的问题是,您必须知道输入的值需要多长时间才能成功。这是一个带有示例的 Stack Overflow 帖子:

Select where first letter in a range ( PostgreSQL )

我还观看了 RailsCasts #343 (Pro),其中讨论了 to_tsvector 和 plainto_tsquery,但坦率地说,我迷路了。也许这是我的答案,但我可以肯定需要一些帮助。这对我来说就像泥巴一样清晰。

【问题讨论】:

  • 为什么不想使用 gem 呢?有很多库可以让这项任务变得更容易。
  • 例如,github.com/ernie/squeel gem。
  • 在我写了这个问题并给出了更多的想法之后,我决定尝试实现 pg_search。我提到的 RailsCasts 中讨论了那个宝石,但当时它很清楚。可能是我看的时候想太多了。我决定再检查一次。我去了 github,看到了如何选择我认为 :prefix 来做开始的功能。这次我成功地实施了它。非常感谢您的投入。我将保存到 squeel 的链接作为参考。

标签: ruby postgresql-9.2


【解决方案1】:
def self.text_search(query)
  if query.present?
    arr = query.split(' ').map { |q| "%#{q}" }

    where('first_name ~~* ANY(ARRAY[:arr]) OR last_name ~~* ANY(ARRAY[:arr])', arr: arr)
  else
    scoped
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多