如何使用Where子句(PostgreSQL)中的变量在Ruby中编写查询

如何使用Where子句(PostgreSQL)中的变量在Ruby中编写查询,ruby,postgresql-9.2,Ruby,Postgresql 9.2,这就是我希望在不使用宝石的情况下实现的目标。我在我的一个视图上有一个搜索功能,我希望允许人们在单个字段中输入名字和姓氏,让我的类方法搜索名字和姓氏,并生成一个列表。我目前有以下丑陋的代码,它将在这两个字段上进行全文搜索。可怜我吧:)我对SQL和PostgreSQL都是新手。我只做了基本的查询 def self.text_search(query) if query.present? q1, q2, q3, q4 = query.split(' ') case

这就是我希望在不使用宝石的情况下实现的目标。我在我的一个视图上有一个搜索功能,我希望允许人们在单个字段中输入名字和姓氏,让我的类方法搜索名字和姓氏,并生成一个列表。我目前有以下丑陋的代码,它将在这两个字段上进行全文搜索。可怜我吧:)我对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)
我还看到了有关检查子字符串并将其与数组进行比较的解决方案。我看到的这个解决方案的问题是,您必须知道输入的值需要多长时间才能成功使用它。下面是一个带有示例的堆栈溢出帖子:


我还观看了RailsCasts#343(Pro),其中讨论了to#tsvector和plainto#tsquery,但坦率地说,我迷路了。也许这是我的答案,但我确实需要一些帮助。对我来说,它就像泥浆一样清澈。

你为什么不想用宝石呢?有很多库可以让这项任务变得更简单。例如,gem。你试过了吗?在我写了这个问题并对此进行了更多思考之后,我决定尝试实现pg_搜索。我提到过的铁路管理者们曾讨论过这块宝石,但在当时,它是一清二楚的。也许我看的时候脑子里想的太多了。我决定再去看看。我去了github,看到了如何选择Ithink:prefix来执行Start with功能。这次我成功地实现了它。非常感谢你的投入。我将保存到squel的链接作为参考。
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