W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
pg_trgm
模塊提供用于決定基于 trigram 匹配的字母數(shù)字文本相似度的函數(shù)和操作符,以及支持快速搜索相似字符串的索引操作符類。
該模塊被認(rèn)為是“trusted”,也就是說,它可以由對(duì)當(dāng)前數(shù)據(jù)庫(kù)具有CREATE
權(quán)限的非超級(jí)用戶安裝。
一個(gè) trigram 是從一個(gè)字符串中取出的由三個(gè)連續(xù)字符組成的組。我們可以通過對(duì)兩個(gè)字符串之間共享的 trigram 計(jì)數(shù)來度量它們的相似度。這種簡(jiǎn)單的思想已經(jīng)成為在很多自然語言中度量詞相似度的有效方法。
在從一個(gè)字符串中提取 trigram 時(shí),pg_trgm
會(huì)忽略非詞字符(非字母數(shù)字)。在決定字符串中所含的 trigram 集合時(shí),每一個(gè)詞被認(rèn)為具有兩個(gè)空格前綴和一個(gè)空格后綴。例如,字符串“cat
”中的 trigram 集合是: “ c
”、
“ ca
”、 “cat
”以及 “at
”。 字符串
“foo|bar
”中的 trigram 集合是: “ f
”、 “ fo
”、
“foo
”、 “oo
”、 “ b
”、
“ ba
”、 “bar
”以及 “ar
”。
pg_trgm
模塊所提供的函數(shù)如表 F.24中所示,操作符則顯示在表 F.25中。
表 F.24. pg_trgm
函數(shù)
考慮下面的例子:
# SELECT word_similarity('word', 'two words');
word_similarity
-----------------
0.8
(1 row)
在第一個(gè)字符串中,trigram集合是{" w"," wo","wor","ord","rd "}
。在第二個(gè)字符串中,trigram的有序集是{" t"," tw","two","wo "," w"," wo","wor","ord","rds","ds "}
。在第二個(gè)字符串中最相似的trigram有序集的部分是{" w"," wo","wor","ord"}
,并且相似度是
0.8
。
這個(gè)函數(shù)返回的值可以大概地理解為第一個(gè)字符串和第二個(gè)字符串任意子串的最大相似度。不過,這個(gè)函數(shù)不會(huì)對(duì)該部分的邊界加入填充。因此,除了失配的詞邊界之外,第二個(gè)字符串中存在的額外字符的數(shù)目沒有被考慮。
同時(shí),strict_word_similarity
在第二個(gè)字符串中選擇一個(gè)由詞構(gòu)成的部分。 在上面的例子中,strict_word_similarity
會(huì)選擇單個(gè)詞'words'
形成的部分, 其trigram集合為{" w"," wo","wor","ord","rds","ds "}
。
# SELECT strict_word_similarity('word', 'two words'), similarity('word', 'words'); strict_word_similarity | similarity ------------------------+------------ 0.571429 | 0.571429 (1 row)
因此,strict_word_similarity
函數(shù)對(duì)于計(jì)算整個(gè)詞的相似度有用,而word_similarity
更適合于計(jì)算詞的部分相似度。
表 F.25. pg_trgm
操作符
操作符 描述 |
---|
如果參數(shù)具有超過 |
如果第一個(gè)參數(shù)中的trigram集合與第二個(gè)參數(shù)中有序trigram集合的一個(gè)連續(xù)部分之間的相似度超過 |
|
如果第二個(gè)參數(shù)有有序trigram集合的一個(gè)連續(xù)部分匹配詞邊界,并且其與第一個(gè)參數(shù)的trigram集合的相似度超過 |
|
返回參數(shù)之間的“距離”,即 1 減去 |
返回參數(shù)之間的“距離”,它是 1 減去 |
|
返回參數(shù)之間的“距離”,也就是1減去 |
|
pg_trgm.similarity_threshold
(real
)
設(shè)置%
操作符使用的當(dāng)前相似度閾值。該閾值必須位于 0 和 1 之間(默認(rèn)是 0.3)。
pg_trgm.word_similarity_threshold
(real
)
設(shè)置<%
和%>
操作符使用的當(dāng)前詞相似度閾值。該閾值必須位于 0 和 1 之間(默認(rèn)是 0.6)。
pg_trgm.strict_word_similarity_threshold
(real
)
設(shè)置<<%
和%>>
運(yùn)算符使用的當(dāng)前嚴(yán)格單詞相似性閾值。 閾值必須介于0和1之間(默認(rèn)值為0.5)。
pg_trgm
模塊提供了 GiST 和 GIN 索引操作符類,這允許你在一個(gè)文本列上創(chuàng)建索引用于快速相似度搜索的目的。這些索引類型支持上述的相似度操作符,并且額外支持基于 trigram 的索引搜索用于LIKE
、ILIKE
、~
和~*
查詢(這些索引不支持等值或簡(jiǎn)單比較操作符,因此你可能還需要一個(gè)常規(guī)的
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);
gist_trgm_ops
GiST opclass 將一組三元組近似為位圖簽名。 它的可選整數(shù)參數(shù)siglen
確定簽名長(zhǎng)度(以字節(jié)為單位)。 默認(rèn)長(zhǎng)度為 12 個(gè)字節(jié)。簽名長(zhǎng)度的有效值介于 1 到 2024 字節(jié)之間。 更長(zhǎng)的簽名導(dǎo)致更精確的搜索(掃描索引的一小部分和更少的堆頁(yè)面),但代價(jià)是更大的索引。
創(chuàng)建簽名長(zhǎng)度為 32 字節(jié)的此類索引的示例:
CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops(siglen=32));
此時(shí),你將有一個(gè)t
列上的索引,你可以用它進(jìn)行相似度搜索。一個(gè)典型的查詢是
SELECT t, similarity(t, 'word
') AS sml
FROM test_trgm
WHERE t % 'word
'
ORDER BY sml DESC, t;
這將返回在文本列中與word
足夠相似的所有值,按最佳匹配到最差匹配的方式排序。索引將被用來讓這種搜索變快,即使在一個(gè)非常大的數(shù)據(jù)集上。
上述查詢的一種變體是
SELECT t, t <-> 'word
' AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
這能夠用 GiST 索引有效地實(shí)現(xiàn),但是用 GIN 索引無法做到。當(dāng)只想要少數(shù)最接近的匹配時(shí),這通常會(huì)比第一種形式更好。
也可以把一個(gè)t
列上的索引用于詞相似度或者嚴(yán)格詞相似度。典型的查詢是:
SELECT t, word_similarity('word
', t) AS sml
FROM test_trgm
WHERE 'word
' <% t
ORDER BY sml DESC, t;
和
SELECT t, strict_word_similarity('word
', t) AS sml
FROM test_trgm
WHERE 'word
' <<% t
ORDER BY sml DESC, t;
這將返回文本列中符合條件的所有值:這些值在其對(duì)應(yīng)的有序trigram集中有一個(gè)連續(xù)部分與word
的trigram集合足夠相似,這些值會(huì)按照最好匹配到最差匹配的順序排列。即便在非常大的數(shù)據(jù)集上,索引也將使得這一操作的速度夠快。
上述查詢可能的變體有:
SELECT t, 'word
' <<-> t AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
和
SELECT t, 'word
' <<<-> t AS dist
FROM test_trgm
ORDER BY dist LIMIT 10;
這可以用 GiST 索引很高效地實(shí)現(xiàn),但是用 GIN 索引不行。
從PostgreSQL 9.1 中開始,這些索引類型也支持用于LIKE
和ILIKE
的索引搜索,例如
SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';
該索引搜索通過從搜索字符串中抽取 trigram 并且在索引中查找它們來工作。搜索字符串中有更多 trigram,索引搜索的效率更高。不像基于 B-樹的搜索,搜索字符串不需要是左錨定的。
從PostgreSQL 9.3 中開始,這些索引類型也支持用于正則表達(dá)式匹配(~
和~*
操作符)的索引搜索,例如
SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';
該索引搜索通過從正則表達(dá)式中抽取 trigram 并且在索引中查找它們來工作。正則表達(dá)式中能抽取出更多 trigram,索引搜索的效率更高。不像基于 B-樹的搜索,搜索字符串不需要是左錨定的。
對(duì)于LIKE
和正則表達(dá)式搜索,記住沒有可抽取 trigram 的模式將退化成一個(gè)全索引掃描。
GiST 和 GIN 索引之間的選擇依賴于 GiST 和 GIN 的相對(duì)性能特性,這在其他地方討論。
在與一個(gè)全文索引聯(lián)合使用時(shí),trigram 匹配是一種非常有用的工具。特別是它能有助于識(shí)別拼寫錯(cuò)誤的輸入詞,這些詞直接用全文搜索機(jī)制是不會(huì)被匹配的。
第一步是生成一個(gè)包含文檔中所有唯一詞的輔助表:
CREATE TABLE words AS SELECT word FROM
ts_stat('SELECT to_tsvector(''simple'', bodytext) FROM documents');
其中documents
是一個(gè)具有我們希望搜索的文本域bodytext
的表。對(duì)to_tsvector
函數(shù)使用simple
配置而不是使用語言相關(guān)的配置的原因是,我們想要一個(gè)原始(沒有去掉詞根的)詞的列表。
接下來,在詞列上創(chuàng)建一個(gè) trigram 索引:
CREATE INDEX words_idx ON words USING GIN(word gin_trgm_ops);
現(xiàn)在,類似于前面例子的一個(gè)SELECT
查詢可以被用來為用戶搜索術(shù)語中的拼寫不當(dāng)?shù)脑~建議拼寫。要求被選擇的詞也與拼寫不當(dāng)?shù)脑~具有相似的長(zhǎng)度是一種有用的額外測(cè)試。
由于words
表已經(jīng)被生成為一個(gè)單獨(dú)的、靜態(tài)的表,它將需要被定期地重新生成,這樣它能合理地與文檔集合保持一致。但是要求它完全與文檔集合同步通常是不必要的。
GiST 開發(fā)站點(diǎn) http://www.sai.msu.su/~megera/postgres/gist/
Tsearch2 開發(fā)站點(diǎn) http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: