pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
pg_trgm模块提供函数和操作符,用于基于三字符组匹配确定 ASCII 文本的相似度, 同时还提供支持快速搜索相似字符串的索引操作符类。
三字符组是一组从字符串中取出的三个连续字符。我们可以通过统计两个字符串共享的三字符组数量来度量它们的相似度。 这个简单的思想在度量许多自然语言中词的相似度时都非常有效。
在确定字符串所包含的三字符组集合时,认为字符串前面有两个空格,后面有一个空格。 例如,字符串“cat”的三字符组集合是 “ c”、 “ ca”、 “cat”和 “at ”。
pg_trgm模块提供的函数列在表 F.24中,操作符列在表 F.25中。
表 F.24. pg_trgm函数
| 函数 | 返回值 | 描述 |
|---|---|---|
similarity(text, text) |
real |
返回一个表示两个参数有多相似的数值。结果范围从 0(表示两个字符串完全不同)到 1(表示两个字符串完全相同)。 |
show_trgm(text) |
text[] |
返回由给定字符串中所有三字符组构成的数组。 (实际应用中,除了调试之外很少有用。) |
show_limit() |
real |
返回%操作符当前使用的相似度阈值。它设置两个单词被视为足够相似、例如可以看作彼此的拼写错误所需的最小相似度。 |
set_limit(real) |
real |
设置%操作符当前使用的相似度阈值。阈值必须介于 0 和 1 之间(默认值为 0.3)。返回传入的相同值。 |
表 F.25. pg_trgm操作符
| 操作符 | 返回值 | 描述 |
|---|---|---|
text % text |
boolean |
如果参数之间的相似度大于set_limit()设置的当前相似度阈值,则返回true。 |
text <-> text |
real |
返回参数之间的“距离”,即 1 减去similarity()的值。 |
pg_trgm模块提供 GiST 和 GIN 索引操作符类,允许你为文本列创建索引,以实现非常快速的相似度搜索。这些索引类型支持上述相似度操作符,还支持对LIKE和ILIKE查询执行基于三字符组的索引搜索。(这些索引不支持等值操作符或简单比较操作符,因此你可能还需要一个常规 B-树索引。)
示例:
CREATE TABLE test_trgm (t text); CREATE INDEX trgm_idx ON test_trgm USING gist (t gist_trgm_ops);
或者
CREATE INDEX trgm_idx ON test_trgm USING gin (t gin_trgm_ops);
此时,你已经在t列上有了一个可用于相似度搜索的索引。典型查询如下:
SELECT t, similarity(t, 'word') AS sml FROM test_trgm WHERE t % 'word' ORDER BY sml DESC, t;
这将返回文本列中所有与以下词足够相似的值:word,按从最佳匹配到最差匹配的顺序排序。即使在非常大的数据集上,索引也会让这一操作保持高效。
上述查询的一种变体是:
SELECT t, t <-> 'word' AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
GiST 索引可以相当高效地实现这一点,但 GIN 索引不能。当只需要少量最接近的匹配项时,它通常会优于第一种写法。
从PostgreSQL9.1 起,这些索引类型还支持以下操作的索引搜索:LIKE以及ILIKE,例如:
SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';
索引搜索的工作方式是从搜索字符串中提取三字符组,然后在索引中查找这些三字符组。搜索字符串中包含的三字符组越多,索引搜索就越有效。与基于 B-树的搜索不同,搜索字符串不需要在左端锚定。
GiST 和 GIN 索引之间如何取舍,取决于二者各自的相对性能特征;相关讨论见其他章节。 作为经验法则,GIN 索引的搜索速度快于 GiST 索引,但构建或更新较慢; 因此 GIN 更适合静态数据,而 GiST 更适合经常更新的数据。
与全文索引结合使用时,三字符组匹配是非常有用的工具。 尤其是,它有助于识别那些因拼写错误而无法被全文检索机制直接匹配的输入词。
第一步是生成一个辅助表,其中包含文档中的全部唯一词:
CREATE TABLE words AS SELECT word FROM
ts_stat('SELECT to_tsvector(''simple'', bodytext) FROM documents');
其中documents是一个表,包含我们希望搜索的文本字段bodytext。 之所以对to_tsvector函数使用simple配置,而不是使用特定语言的配置, 是因为我们需要原始的(未经词干提取的)词列表。
接下来,在词列上创建一个三字符组索引:
CREATE INDEX words_idx ON words USING gin (word gin_trgm_ops);
现在,可以使用与前面示例类似的SELECT查询,为用户搜索词中拼错的单词提供拼写建议。 一个有用的附加测试是要求选出的词长度也与该拼错单词相近。
由于words表是作为一张独立的静态表生成的,因此需要定期重新生成, 以便与文档集合保持大致同步。 通常没有必要让它始终保持精确同步。
GiST 开发站点 http://www.sai.msu.su/~megera/postgres/gist/
Tsearch2 开发站点 http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/
Oleg Bartunov <oleg@sai.msu.su>,俄罗斯莫斯科,莫斯科大学
Teodor Sigaev <teodor@sigaev.ru>,俄罗斯莫斯科,Delta-Soft Ltd.
文档:Christopher Kings-Lynne
本模块由俄罗斯莫斯科的 Delta-Soft Ltd. 赞助。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。