搜索字符串中的单个单词

10 postgresql search full-text-search

我知道全文搜索,但这只是针对单个单词的查询.我想选择包含以查询中的单词开头的单词的字符串.例如,如果我搜索:

appl
Run Code Online (Sandbox Code Playgroud)

以下内容应匹配:

a really nice application
apples are cool
appliances
Run Code Online (Sandbox Code Playgroud)

因为所有这些字符串都包含以...开头的单词appl.另外,如果我可以选择匹配的单词数量,并根据它进行排序,那将是很好的.

我怎样才能在PostgreSQL中实现它?

Ham*_*bba 9

SELECT * FROM some_table WHERE some_field LIKE 'appl%' OR some_field LIKE '% appl%';
Run Code Online (Sandbox Code Playgroud)

至于计算匹配的单词数量,我相信在postgres中动态执行会太昂贵(尽管其他人可能知道的更好).一种方法是通过编写一个函数来计算字符串中的出现次数,然后添加ORDER BY myFunction('appl', some_field).但是,这种方法非常昂贵(即很慢),不推荐使用.

对于这样的事情,你应该使用单独/免费的全文搜索引擎,如Sphinx Search(google it),这是专门针对那种事情的.

另一种方法是使另一个表包含关键字以及每个字符串中这些关键字的出现次数.这意味着你需要存储你有每个词组(如really really nice application)以及关键字存储在另一个表(即really, 2,nice, 1,application, 1)和关键词表链接到您的满语表.这意味着在将字符串输入数据库并将它们存储在两个位置时,您必须将字符串分解为关键字.这是典型的空间与速度的权衡.


Erw*_*ter 8

前缀与全文搜索匹配

几年后重新审视这个问题,让我感到震惊,FTS 确实支持前缀匹配.您的查询可以像这样工作:

SELECT * FROM tbl
WHERE  to_tsvector('simple', string) @@ to_tsquery('simple', 'appl:*');
Run Code Online (Sandbox Code Playgroud)

请注意附加:*的内容tsquery.细节:

替代正则表达式

SELECT * FROM tbl
WHERE  string ~ '\mappl';
Run Code Online (Sandbox Code Playgroud)

在这里引用手册:

\m ..仅匹配单词的开头

要按比赛计数,您可以使用 regexp_matches()

SELECT tbl_id, count(*) AS matches
FROM  (
    SELECT tbl_id, regexp_matches(string, '\mappl', 'g')
    FROM   tbl
    WHERE  string ~ '\mappl'
    ) sub
GROUP  BY 1
ORDER  BY 2 DESC;
Run Code Online (Sandbox Code Playgroud)

或者regexp_split_to_table():

SELECT tbl_id, string, count(*) - 1 AS matches
FROM  (
    SELECT tbl_id, string, regexp_split_to_table(string, '\mappl')
    FROM   tbl
    WHERE  string ~ '\mappl'
    ) sub
GROUP  BY 1, 2
ORDER  BY 3 DESC, 2, 1;
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle演示了这三个.

Postgres 9.3甚至为简单的正则表达式提供索引支持,具有trigram GIN或GiST索引(引用发行说明):

添加对pg_trgm中正则表达式搜索索引的支持(​​Alexander Korotkov)

Depesz写了一篇关于新功能的博客.