使用 Postgres 全文搜索搜索完全匹配的最佳方法是啥?
Posted
技术标签:
【中文标题】使用 Postgres 全文搜索搜索完全匹配的最佳方法是啥?【英文标题】:What is the best way to search for an exact match using Postgres full-text search?使用 Postgres 全文搜索搜索完全匹配的最佳方法是什么? 【发布时间】:2016-08-02 01:13:26 【问题描述】:我有一个包含大约 150 万条记录的 Postgres 数据库。在我的 Ruby on Rails 应用程序中,我需要搜索 statement_text
字段(可以包含 1 到数百个单词)。
我的问题:我知道我可以使用pgSearch
gem 来创建像search_all_words
或search_any_words
这样的范围,但我不确定确保只有完全匹配的记录的最有效方法是什么 在结果集中返回。
也就是说,如果我搜索“教皇弗朗西斯”,我希望它只找到连续且顺序相同的这两个词(而不是说,“教皇名叫弗朗西斯”)。
到目前为止,我刚刚将 GIN 索引与 ILIKE
结合起来进行精确匹配搜索。但是考虑到 GIN 索引在每条记录中基本上都由storing the exact position of a word 起作用,难道不应该有更有效的(非ILIKE
)方法来确保搜索词与字段完全匹配吗?
【问题讨论】:
【参考方案1】:一般来说,全文需要根据所使用的语言词典进行词干提取,因此使用全文搜索可以使用 ts_rank()
函数而不使用 词干 和 'simple'
词典来确定您正在搜索的短语的相关性。
WITH t(v) AS ( VALUES
('Test sentence with Pope Francis'),
('Test Francis sentence with Pope '),
('The pope is named Francis')
)
SELECT v,ts_rank(tsv,q) as rank
FROM t,
to_tsvector('simple',v) as tsv,
plainto_tsquery('simple','Pope Francis') AS q;
结果:
v | rank
----------------------------------+-----------
Test sentence with Pope Francis | 0.0991032
Test Francis sentence with Pope | 0.0973585
The pope is named Francis | 0.0973585
(3 rows)
没有全文搜索,您可以使用pg_trgm
扩展名实现更快的ILIKE
模式匹配。例如here。
【讨论】:
谢谢,德米特里!我正在使用全文搜索,所以我可以使用 ts_rank。但是,问题在于——取决于字段的字数——没有特定的截止点可以确保单词相邻且顺序正确,而无需使用 ILIKE。我理解正确吗? 不,没有基于长度的截断。如果短语匹配,它仍然会有更高的排名。您可以省略 ts_rank 的归一化因子 - 它应该可以正常工作。以上是关于使用 Postgres 全文搜索搜索完全匹配的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
关于全文搜索elasticsearch中matchQuery和termQuery的区别