【发布时间】:2011-07-18 06:45:52
【问题描述】:
如果我在数据库中存储了这样的字符串/短语:
- 什么是 Q 型操作?
- 程序员指南
- A.B.C 的编码
有没有办法像"Programmers"或"abc"或"q-type"一样传递查询参数并让它找到"Programmer's"、"A.B.C"和"Q-type"?
【问题讨论】:
标签: sql postgresql search
如果我在数据库中存储了这样的字符串/短语:
- 什么是 Q 型操作?
- 程序员指南
- A.B.C 的编码
有没有办法像"Programmers"或"abc"或"q-type"一样传递查询参数并让它找到"Programmer's"、"A.B.C"和"Q-type"?
【问题讨论】:
标签: sql postgresql search
您可以尝试使用带有 TRANSLATE 功能的 ILIKE,请参阅 here。
例如:translate(field, '.-\'', '')
【讨论】:
Article.find(:conditions => ["translate(articles.title, '.-\'', '') ILIKE ?", query]) throws ...unterminated quoted string... (尝试了几种转义方法)。可能与 tsvector 一起使用,更可能是 solr。谢谢!
''
Article.find(:conditions => [ %q{translate(articles.title, '.-\'', '') ILIKE ?}, query])。否则 ruby 将捕获您试图传递给 sql 的 \,并且您必须使用 2 或 3 个 '\'。 Ruby 不会像双引号字符串那样在单引号字符串中转义。即puts('1\n2'); puts("3\n4") #=> 1\n2*newline*3*newline*4*newline*
这听起来像你想要一些类似的东西:
http://www.postgresql.org/docs/9.0/static/fuzzystrmatch.html
我不能 100% 确定这是否能满足您的需求。
编辑我必须在本地运行它来检查(在 Windows 上使用 PostgreSQL 9.0)
这是我发现的:
template1=> select soundex('Programmers'), soundex('Programmer''s');
soundex | soundex
---------+---------
P626 | P626
(1 row)
template1=> select soundex('abc'), soundex('A.B.C.');
soundex | soundex
---------+---------
A120 | A120
(1 row)
template1=> select soundex('Q-type'), soundex('q-type');
soundex | soundex
---------+---------
Q310 | Q310
(1 row)
因此,如果您要执行 soundex(colname) = soundex(<user param>) 应该会在 where 子句中为您提供所需的内容。
您需要安装 fuzzystrmatch 模块:
psql -U <dbowner> -d <database> -f SHAREDIR/contrib/fuzzystrmatch.sql
请参阅有关如何定位 SHAREDIR
的文档编辑我刚刚注意到我忽略了什么,我认为这与ts_vector 功能相结合可能会让您达到您的目标。
【讨论】:
这是另一个相关的链接。在将其与搜索字符串进行比较之前,从所有标点符号中去除该字段的值。
【讨论】:
Postgres 支持模式匹配,因此您可以在 where 子句中构建正则表达式 http://www.postgresql.org/docs/8.3/static/functions-matching.html
【讨论】:
使用 tsvector 类型,它是 PostgreSQL 文本搜索功能的一部分。
postgres> select 'What are Q-type Operations?'::tsvector;
tsvector
-------------------------------------
'Operations?' 'Q-type' 'What' 'are'
(1 row)
您也可以在 tsvector 上使用熟悉的运算符:
postgres> select 'What are Q-type Operations?'::tsvector
postgres> || 'A.B.C''s of Coding'::tsvector;
?column?
--------------------------------------------------------------
'A.B.C''s' 'Coding' 'Operations?' 'Q-type' 'What' 'are' 'of'
tsvector 值是不同词位的排序列表,这些词是经过规范化以合并同一词的不同变体的词(有关详细信息,请参阅第 12 章)。在输入过程中自动完成排序和重复消除
如果您还想进行特定于语言的规范化,例如删除常用词(“the”、“a”等)和乘法,请使用 to_tsvector 函数。它还为文本搜索的不同单词分配权重:
postgres> select to_tsvector('english',
postgres> 'What are Q-type Operations? A.B.C''s of Coding');
to_tsvector
--------------------------------------------------------
'a.b.c':7 'code':10 'oper':6 'q':4 'q-type':3 'type':5
(1 row)
显然,对查询中的每一行都这样做会很昂贵——因此您应该将 tsvector 存储在单独的列中并使用 ts_query() 来搜索它。这也允许您在 tsvector 上创建一个 GiST 索引。
postgres> insert into text (phrase, tsvec)
postgres> values('What are Q-type Operations?',
postgres> to_tsvector('english', 'What are Q-type Operations?'));
INSERT 0 1
使用 tsquery 和 @@ 运算符完成搜索:
postgres> select phrase from text where tsvec @@ to_tsquery('q-type');
phrase
-----------------------------
What are Q-type Operations?
(1 row)
【讨论】:
Postgresql 通过将文本输入转换为tsvector 类型来支持全文搜索:
steve@steve@[local] =# select input, to_tsvector('english', input)\
from (values('What are Q-type Operations?'),('Programmer''s Guide'),('A.B.C''s of Coding')) x(input);
input | to_tsvector
-----------------------------+------------------------------------
What are Q-type Operations? | 'oper':6 'q':4 'q-type':3 'type':5
Programmer's Guide | 'guid':3 'programm':1
A.B.C's of Coding | 'a.b.c':1 'code':4
(3 rows)
如您所见,默认使用的词干将使“programming”、“programmer”和“programmer's”完全匹配。
您通常会通过索引 tsvector 列或表达式来使用它,然后使用 @@ 运算符将其与 tsquery 匹配,例如:
steve@steve@[local] =# select input, to_tsvector('english', input) \
from (values('What are Q-type Operations?'),('Programmer''s Guide'),('A.B.C''s of Coding')) x(input)\
where to_tsvector('english', input) @@ plainto_tsquery('english', 'programmers');
input | to_tsvector
--------------------+-----------------------
Programmer's Guide | 'guid':3 'programm':1
(1 row)
plainto_tsquery 在这里分析用户输入字符串,并生成一个查询,其中查询中的每个非停用词都必须由 tsvector 匹配。
【讨论】: