14

I know about full-text search, but that only matches your query against individual words. I want to select strings that contain a word that starts with words in my query. For example, if I search:

appl

the following should match:

a really nice application
apples are cool
appliances

since all those strings contains words that start with appl. In addition, it would be nice if I could select the number of words that match, and sort based on that.

How can I implement this in PostgreSQL?

4

2 回答 2

16

与全文搜索匹配的前缀

FTS 支持前缀匹配。您的查询是这样工作的:

SELECT * FROM tbl
WHERE  to_tsvector('simple', string) @@ to_tsquery('simple', 'appl:*');

注意附加:*tsquery. 这可以使用索引。看:

用正则表达式替代

SELECT * FROM tbl
WHERE  string ~ '\mappl';

在这里引用手册

\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 tbl_id
ORDER  BY matches DESC;

或者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;

db<>fiddle here
sqlfiddle

Postgres 9.3 或更高版本具有对带有 trigram GIN 或 GiST 索引的简单正则表达式的索引支持。Postgres 9.3 的发行说明:

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

看:

Depesz 写了一篇关于正则表达式的索引支持的博客。

于 2013-10-15T04:01:31.227 回答
11
SELECT * FROM some_table WHERE some_field LIKE 'appl%' OR some_field LIKE '% appl%';

至于计算匹配的单词数,我认为在 postgres 中动态地做这件事太昂贵了(尽管也许其他人知道得更好)。一种方法是编写一个计算字符串中出现次数的函数,然后添加ORDER BY myFunction('appl', some_field). 同样,这种方法非常昂贵(即缓慢),不推荐使用。

对于这样的事情,你可能应该使用一个单独的/免费的全文搜索引擎,比如 Sphinx Search (google it),它专门用于这类事情。

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

于 2013-10-14T21:21:10.167 回答