2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不再支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3

F.16. fuzzystrmatch — 確定字串相似度和距離 #

fuzzystrmatch 模組提供了幾個函式來確定字串之間的相似度和距離。

注意

目前,soundexmetaphonedmetaphonedmetaphone_alt 函式在處理多位元組編碼(如 UTF-8)時效果不佳。對於此類資料,請使用 daitch_mokotofflevenshtein

此模組被認為是受信任的,這意味著非超級使用者也可以在其擁有的資料庫上安裝它,前提是他們具有 CREATE 許可權。

F.16.1. Soundex #

Soundex 系統是一種透過將發音相似的名稱轉換為相同程式碼來匹配它們的方法。它最初由美國人口普查局在 1880、1900 和 1910 年使用。請注意,Soundex 對於非英語名稱不太有用。

fuzzystrmatch 模組提供了兩個用於處理 Soundex 編碼的函式:

soundex(text) returns text
difference(text, text) returns int

soundex 函式將字串轉換為其 Soundex 編碼。difference 函式將兩個字串轉換為它們的 Soundex 編碼,然後報告匹配程式碼位置的數量。由於 Soundex 編碼有四個字元,因此結果的範圍是從零到四,其中零表示不匹配,四表示完全匹配。(因此,該函式名稱不恰當 — similarity 會是更好的名稱。)

以下是一些使用示例:

SELECT soundex('hello world!');

SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann');
SELECT soundex('Anne'), soundex('Andrew'), difference('Anne', 'Andrew');
SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');

CREATE TABLE s (nm text);

INSERT INTO s VALUES ('john');
INSERT INTO s VALUES ('joan');
INSERT INTO s VALUES ('wobbly');
INSERT INTO s VALUES ('jack');

SELECT * FROM s WHERE soundex(nm) = soundex('john');

SELECT * FROM s WHERE difference(s.nm, 'john') > 2;

F.16.2. Daitch-Mokotoff Soundex #

與原始 Soundex 系統類似,Daitch-Mokotoff Soundex 透過將發音相似的名稱轉換為相同程式碼來匹配它們。然而,Daitch-Mokotoff Soundex 對於非英語名稱比原始系統更有用。相比原始系統,主要改進包括:

  • 程式碼基於前六個有意義的字母,而不是四個。

  • 一個字母或字母組合對映到十種可能的程式碼,而不是七種。

  • 當兩個連續的字母具有單一發音時,它們被編碼為單個數字。

  • 當一個字母或字母組合可能具有不同的發音時,會發出多個程式碼以覆蓋所有可能性。

此函式為輸入生成 Daitch-Mokotoff soundex 程式碼。

daitch_mokotoff(source text) returns text[]

結果可能包含一個或多個程式碼,具體取決於有多少種可能的發音,因此它被表示為一個數組。

由於 Daitch-Mokotoff soundex 程式碼僅包含 6 位數字,因此 source 最好是單個單詞或名稱。

以下是一些示例:

SELECT daitch_mokotoff('George');
 daitch_mokotoff
-----------------
 {595000}

SELECT daitch_mokotoff('John');
 daitch_mokotoff
-----------------
 {160000,460000}

SELECT daitch_mokotoff('Bierschbach');
                      daitch_mokotoff
-----------------------------------------------------------
 {794575,794574,794750,794740,745750,745740,747500,747400}

SELECT daitch_mokotoff('Schwartzenegger');
 daitch_mokotoff
-----------------
 {479465}

對於單個名稱的匹配,可以使用 && 運算子直接匹配返回的文字陣列:任何重疊都可以視為匹配。可以使用 GIN 索引來提高效率,請參閱 第 65.4 節 和此示例。

CREATE TABLE s (nm text);
CREATE INDEX ix_s_dm ON s USING gin (daitch_mokotoff(nm)) WITH (fastupdate = off);

INSERT INTO s (nm) VALUES
  ('Schwartzenegger'),
  ('John'),
  ('James'),
  ('Steinman'),
  ('Steinmetz');

SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Swartzenegger');
SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Jane');
SELECT * FROM s WHERE daitch_mokotoff(nm) && daitch_mokotoff('Jens');

對於任何數量名稱的任意順序的索引和匹配,可以使用全文搜尋功能。請參閱 第 12 章 和此示例。

CREATE FUNCTION soundex_tsvector(v_name text) RETURNS tsvector
BEGIN ATOMIC
  SELECT to_tsvector('simple',
                     string_agg(array_to_string(daitch_mokotoff(n), ' '), ' '))
  FROM regexp_split_to_table(v_name, '\s+') AS n;
END;

CREATE FUNCTION soundex_tsquery(v_name text) RETURNS tsquery
BEGIN ATOMIC
  SELECT string_agg('(' || array_to_string(daitch_mokotoff(n), '|') || ')', '&')::tsquery
  FROM regexp_split_to_table(v_name, '\s+') AS n;
END;

CREATE TABLE s (nm text);
CREATE INDEX ix_s_txt ON s USING gin (soundex_tsvector(nm)) WITH (fastupdate = off);

INSERT INTO s (nm) VALUES
  ('John Doe'),
  ('Jane Roe'),
  ('Public John Q.'),
  ('George Best'),
  ('John Yamson');

SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('john');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('jane doe');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('john public');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('besst, giorgio');
SELECT * FROM s WHERE soundex_tsvector(nm) @@ soundex_tsquery('Jameson John');

如果希望避免在索引重新檢查期間重新計算 soundex 程式碼,可以使用單獨列上的索引代替表示式上的索引。可以使用儲存的生成列來實現此目的;請參閱 第 5.4 節

F.16.3. Levenshtein #

此函式計算兩個字串之間的 Levenshtein 距離。

levenshtein(source text, target text, ins_cost int, del_cost int, sub_cost int) returns int
levenshtein(source text, target text) returns int
levenshtein_less_equal(source text, target text, ins_cost int, del_cost int, sub_cost int, max_d int) returns int
levenshtein_less_equal(source text, target text, max_d int) returns int

sourcetarget 都可以是非空字串,最大長度為 255 個字元。成本引數指定字元插入、刪除或替換的費用。您可以省略成本引數,就像函式第二個版本那樣;在這種情況下,所有引數都預設為 1。

levenshtein_less_equal 是 Levenshtein 函式的一個加速版本,用於只關心小距離的情況。如果實際距離小於或等於 max_d,則 levenshtein_less_equal 返回正確距離;否則,它將返回一個大於 max_d 的值。如果 max_d 為負數,則行為與 levenshtein 相同。

示例

test=# SELECT levenshtein('GUMBO', 'GAMBOL');
 levenshtein
-------------
           2
(1 row)

test=# SELECT levenshtein('GUMBO', 'GAMBOL', 2, 1, 1);
 levenshtein
-------------
           3
(1 row)

test=# SELECT levenshtein_less_equal('extensive', 'exhaustive', 2);
 levenshtein_less_equal
------------------------
                      3
(1 row)

test=# SELECT levenshtein_less_equal('extensive', 'exhaustive', 4);
 levenshtein_less_equal
------------------------
                      4
(1 row)

F.16.4. Metaphone #

Metaphone 與 Soundex 一樣,基於為輸入字串構造代表性程式碼的思想。然後,如果兩個字串具有相同的程式碼,則認為它們相似。

此函式計算輸入字串的 metaphone 程式碼。

metaphone(source text, max_output_length int) returns text

source 必須是非空字串,最大長度為 255 個字元。max_output_length 設定輸出 metaphone 程式碼的最大長度;如果超過此長度,輸出將被截斷為該長度。

示例:

test=# SELECT metaphone('GUMBO', 4);
 metaphone
-----------
 KM
(1 row)

F.16.5. Double Metaphone #

Double Metaphone 系統為給定的輸入字串計算兩個“聽起來像”的字串——一個“主要”和一個“備選”。在大多數情況下它們是相同的,但對於非英語名稱尤其可能略有不同,具體取決於發音。這些函式計算主要和備選程式碼。

dmetaphone(source text) returns text
dmetaphone_alt(source text) returns text

輸入字串沒有長度限制。

示例:

test=# SELECT dmetaphone('gumbo');
 dmetaphone
------------
 KMP
(1 row)

提交更正

如果您在文件中發現任何不正確、與您在使用特定功能時的體驗不符或需要進一步澄清的內容,請使用此表格報告文件問題。