pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
pg_trgm 模块提供函数和操作符,用于基于三元组 匹配确定 ASCII 字母数字文本的相似度,同时还提供支持快速搜索相似 字符串的索引操作符类。
三字符组是一组从字符串中取出的三个连续字符。我们可以通过统计两个字符串共享的三字符组数量来度量它们的相似度。 这个简单的思想在度量许多自然语言中词的相似度时都非常有效。
在确定字符串所包含的三元组集合时,认为字符串前面有两个空格, 后面有一个空格。例如,字符串 “cat” 的三元组集合是 “ c”、 “ ca”、 “cat” 和 “at ”.
pg_trgm模块提供的函数列在表 F.24中,操作符列在表 F.25中。
表 F.24. pg_trgm函数
| Function | Returns | Description |
|---|---|---|
similarity(text, text) |
real |
Returns a number that indicates how similar the two arguments are. The range of the result is zero (indicating that the two strings are completely dissimilar) to one (indicating that the two strings are identical). |
show_trgm(text) |
text[] |
Returns an array of all the trigrams in the given string. (In practice this is seldom useful except for debugging.) |
show_limit() |
real |
Returns the current similarity threshold used by the % operator. This sets the minimum similarity between two words for them to be considered similar enough to be misspellings of each other, for example. |
set_limit(real) |
real |
Sets the current similarity threshold that is used by the % operator. The threshold must be between 0 and 1 (default is 0.3). Returns the same value passed in. |
表 F.25. pg_trgm操作符
| Operator | Returns | Description |
|---|---|---|
text % text |
boolean |
Returns true if its arguments have a similarity that is greater than the current similarity threshold set by set_limit. |
text <-> text |
real |
Returns the “distance” between the arguments, that is one minus the similarity() value. |
pg_trgm 模块提供了 GiST 和 GIN 索引操作符类,允许你在文本列上建立索引,用于极快的相似度搜索。 These index types support the above-described similarity operators, and additionally support trigram-based index searches for LIKE and ILIKE queries. (These indexes do not support equality nor simple comparison operators, so you may need a regular B-tree index too.)
示例:
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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。