首页 > 解决方案 > 是否有一个多字节感知 Postgresql Levenshtein?

问题描述

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

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

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

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

目前,soundex、metaphone、dmetaphone 和 dmetaphone_alt 函数不适用于多字节编码(例如 UTF-8)。

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

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

标签: postgresqlutf-8levenshtein-distance

解决方案


注意:@Nick Barnes 在他对相关问题的回答中建议了此解决方案。

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

有一个等效的预组合字符ąE'\u0105'

一种解决方案是规范化Unicode 字符串,即在比较它们之前将组合字符序列转换为预先组合的字符。

不幸的是,Postgres 似乎没有内置的 Unicode 规范化功能,但您可以通过PL/PerlPL/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;

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

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

推荐阅读