PostgreSQL全文搜索和Trigram混淆

50

我对PostgreSQL、全文检索和 Trigram 的整个概念有点困惑。在我的全文检索查询中,我使用 tsvectors,就像这样:

SELECT * FROM articles
WHERE search_vector @@ plainto_tsquery('english', 'cat, bat, rat');

问题在于,此方法没有考虑到拼写错误。然后我开始阅读关于 Trigram和pg_trgm的内容:

通过查看其他示例,似乎使用了trigram或向量,但从未同时使用。那么我的问题是:它们是否可以一起使用?如果可以,如何使用?trigram是否可以替代全文检索?trigram是否更准确?trigram的性能如何?

1个回答

74
它们有着非常不同的用途。
全文搜索用于返回与搜索查询匹配的词干词的文档。
三元组提供了一种比较两个字符串并确定它们相似程度的方法。
请考虑以下示例:
SELECT 'cat' % 'cats'; --true

以上返回true,因为'cat'与'cats'非常相似(由pg_trgm限制决定)。
SELECT 'there is a cat with a dog' % 'cats'; --false

以上返回false,因为%是在寻找两个完整字符串之间的相似性,而不是在字符串中寻找单词cats
SELECT to_tsvector('there is a cat with a dog') @@ to_tsquery('cats'); --true

这返回true,因为tsvector将字符串转换为一组词干化的单词,并忽略了一些常见词(停用词-如'is'和'a')...然后搜索词干化版本的cats
听起来你想使用trigrams来自动纠正你的ts_query,但这实际上并不可能(至少没有高效的方式)。它们并不真正知道一个单词是否拼写错误,只知道它与另一个单词的相似程度。它们可以用于搜索一个单词表,尝试找到相似的单词,从而实现“你是不是想说...”类型的功能,但这需要维护一个单独的表,其中包含您search字段中使用的所有单词。
如果您有一些常常拼写错误的单词/短语,希望文本索引能够匹配,您可能需要查看同义词词典

2
我添加了一些示例来突出每个扩展中%@@之间的区别。如果您的目标是查找包含英语(或任何您拥有字典的已知语言)的文档,则需要全文搜索。如果您的目标是将整个字段与具有一定容错率的字符串进行匹配,以便处理拼写错误,则应使用pg_trgm。 - Chris Farmiloe
谢谢解释!这让我明白了很多。好的,看起来问题可以通过扩展我的字典知识来解决。 - Devin Dixon
16
我喜欢这个答案。我讨厌这个答案是准确的这个事实 :( - courtsimas
7
自Postgres 9.6版本起,三合一模块(pg_trgm)已具备“单词相似度”功能。这意味着它可以查找字符串中最相似的单词,而不是将查询与整个字符串进行比较。 - Inkling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接