搜索字符串中的单个单词
Posted
技术标签:
【中文标题】搜索字符串中的单个单词【英文标题】:Searching individual words in a string 【发布时间】:2013-10-22 13:30:44 【问题描述】:我知道全文搜索,但这只会将您的查询与单个单词匹配。我想选择包含以我的查询中的单词开头的单词的字符串。例如,如果我搜索:
appl
以下内容应匹配:
a really nice application
apples are cool
appliances
因为所有这些字符串都包含以appl
开头的单词。另外,如果我能选择匹配的单词数量,并以此为基础进行排序,那就太好了。
如何在 PostgreSQL 中实现这一点?
【问题讨论】:
【参考方案1】:全文搜索的前缀匹配
FTS 支持前缀匹配。您的查询是这样的:
SELECT * FROM tbl
WHERE to_tsvector('simple', string) @@ to_tsquery('simple', 'appl:*');
注意tsquery
中附加的:*
。这可以使用索引。
见:
正则表达式替代
SELECT * FROM tbl
WHERE string ~ '\mappl';
引用the manual here:
\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小提琴here旧sqlfiddle
Postgres 9.3 或更高版本具有索引支持,用于带有三元组 GIN 或 GiST 索引的简单正则表达式。 The release notes for Postgres 9.3:
在 pg_trgm 中添加对正则表达式搜索索引的支持 (亚历山大·科罗特科夫)
见:
PostgreSQL LIKE query performance variationsDepesz 写了一个blog about index support for regular expressions.
【讨论】:
SELECT * FROM tbl WHERE to_tsvector('simple', string) @@ to_tsquery('simple', 'appl:*');这适用于字符串,但不适用于数字 SELECT * FROM tbl WHERE to_tsvector('simple', string) @@ to_tsquery('simple', '111');这不起作用 @dev_sk:为我工作。 db小提琴here【参考方案2】: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
)并将该关键字表链接到您的完整短语表。这意味着您必须在将字符串输入数据库时将它们分解为关键字并将它们存储在两个位置。这是典型的空间与速度权衡。
【讨论】:
我现在正在阅读LIKE
。如果我在搜索查询中有多个单词怎么办?如果我想搜索 appl goog
并匹配 Apple and Google are good companies
怎么办?
SELECT * FROM some_table WHERE (some_field LIKE 'appl%' OR some_field LIKE '% appl%') AND (some_field LIKE 'goog%' OR some_field LIKE '% goog%');
我想强调的是,这是一种骇人听闻的方式。例如,以下内容与 appl
搜索不匹配:"apples are my favorite!" exclaimed the boy.
因为在 appl 之前有一个 "。此外,您可能希望使用 ILIKE(用于不区分大小写的搜索)。以上是关于搜索字符串中的单个单词的主要内容,如果未能解决你的问题,请参考以下文章
10 位或 6 位数字的正则表达式不应以“/”开头和结尾,也可以是字符串中的单个单词 [重复]