fuzzystrmatch
模块提供多个函数来确定字符串之间的相似性和距离。
目前,soundex
、metaphone
、dmetaphone
和 dmetaphone_alt
函数不支持多字节编码(例如 UTF-8)。对于此类数据,请使用 daitch_mokotoff
或 levenshtein
。
此模块被认为是““受信任的””,即它可以由在当前数据库上拥有 CREATE
权限的非超级用户安装。
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;
与原始 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 索引用于提高效率,请参见 第 64.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 节。
此函数计算两个字符串之间的 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
source
和 target
既可以是长度不超过 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)
Metaphone 与 Soundex 一样,基于为输入字符串构建代表性代码的理念。然后,如果两个字符串具有相同的代码,则认为它们相似。
此函数计算输入字符串的元音代码
metaphone(source text, max_output_length int) returns text
source
必须是长度不超过 255 个字符且非空的字符串。
示例
test=# SELECT metaphone('GUMBO', 4); metaphone ----------- KM (1 row)
对于给定的输入字符串,Double Metaphone 系统计算两个 “发音类似” 字符串——一个 “主要” 字符串和一个 “备选” 字符串。在大多数情况下,它们是相同的,但对于非英语名称来说,它们尤其可能存在一些差异,具体取决于发音。这些函数计算主要代码和备选代码
dmetaphone(source text) returns text dmetaphone_alt(source text) returns text
输入字符串没有长度限制。
示例
test=# SELECT dmetaphone('gumbo'); dmetaphone ------------ KMP (1 row)