【发布时间】: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