是否有多字节感知的 Postgresql Levenshtein?

Is there a multibyte-aware Postgresql Levenshtein?

当我使用带有变音符号的 fuzzystrmatch levenshtein 函数时,它 returns 一个错误的/多字节无知的结果:

select levenshtein('ą', 'x');
levenshtein 
-------------
       2

(注意:第一个字符是'a',下面有变音符号,我在这里复制后显示不正确)

fuzzystrmatch 文档 (https://www.postgresql.org/docs/9.1/fuzzystrmatch.html) 警告说:

At present, the soundex, metaphone, dmetaphone, and dmetaphone_alt functions do not work well with multibyte encodings (such as UTF-8).

但是因为它没有命名 levenshtein 函数,我想知道是否有 levenshtein 的多字节感知版本。

我知道我可以使用 unaccent 函数作为解决方法,但我需要保留变音符号。

Note: This solution was suggested by @Nick Barnes in his to a .

带有变音符号的'a'是一个字符序列,即a和组合字符的组合,变音符号̨:E'a\u0328'

有一个等价的预组字±E'\u0105'

一个解决方案是 normalise Unicode 字符串,即在比较它们之前将组合字符序列转换为预组合字符。

不幸的是,Postgres 似乎没有 built-in Unicode 规范化功能,但您可以通过 PL/Perl or PL/Python 语言扩展轻松访问。

例如:

create extension plpythonu;

create or replace function unicode_normalize(str text) returns text as $$
  import unicodedata
  return unicodedata.normalize('NFC', str.decode('UTF-8'))
$$ language plpythonu;

现在,由于使用unicode_normalize将字符序列E'a\u0328'映射到等效的预组合字符E'\u0105',因此编辑距离是正确的:

select levenshtein(unicode_normalize(E'a\u0328'), 'x');
levenshtein
-------------
           1