【问题标题】:utf-8 string similarity in postgresql 10.1postgresql 10.1 中的 utf-8 字符串相似度
【发布时间】:2018-11-27 10:58:59
【问题描述】:

:) 我正在尝试在 PostgreSQL 10.1 中查找字符串相似性。

我使用扩展名 unaccentpg_trgm 并通过以下方式启用它们:

create extension unaccent;
create extension pg_trgm;

问题是pg_trgm不提供utf8支持。所以如果我执行:

select similarity('כפיר','כפיר');

返回相似度为零。

我决定将该字符串转换为支持希伯来语和英语的 iso-8859-8 编码,我在这种情况下使用的语言。

但首先我想unaccent 字符串,所以如果我有כפיר - ƒ,它将首先转换为כפיר - f,以便正确转换为所需的字符编码。

所以select unaccent('כפיר - ƒ'); 确实返回了正确的结果。

所以不幸执行:

select convert(unaccent('כפיר - ƒ'),'UTF8','ISO_8859_8');

返回

[42883] 错误:函数转换(文本,未知,未知)不存在提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。位置:8

当我在 https://www.postgresql.org/docs/9.1/functions-string.html 查看有关 convert() 函数的文档时,它需要一个字符串。

如果我尝试将某些内容转换为字符串,我会得到 type "string" does not exist

好的。因此,使用 unaccent 是我需要解决的第一个问题(也许是唯一的问题)。我接下来所做的操作返回了正确的结果,而我却没有看到希伯来语中的正确字符串。

我的意思是这个..

执行select convert('כפיר','UTF-8','ISO_8859_8'); 返回

4 B 00000000  EB F4 E9 F8                                        ëôéø

并使用select convert('כפיר','UTF8','ISO_8859_8')::text; 将其转换为文本返回\xebf4e9f8

我猜这些是写字符,由于编码的变化,我看不到实际的希伯来字符。我认为这是错误的吗?这是第二个问题。

所以如果我不使用重音并执行:

select similarity(convert('כפייר עזר','UTF8','ISO_8859_8')::text, convert('כפיר','UTF8','ISO_8859_8')::text);

它返回的相似度为 0.5,这是可以的。

总结一下,我的问题是:

  1. 如何正确转换unaccent 以便能够在convert 中使用它
  2. 我是否将我的 utf-8 希伯来语字符串正确地转换为 ASCII?
  3. 我是否正在尝试以正确的方式解决问题 - 是否存在支持 utf-8 的相似函数的不同扩展?
  4. 我还想在执行相似性函数之前从字符串中删除任何不是字母数字的字符,以便根据我的需要获得更好的相似性结果。我考虑使用正则表达式将字符串转换为 ASCII。类似:regexp_replace('string', '\W+', '', 'g')。这是要走的路吗?有支持 utf8 的 regexp_replace 吗?

谢谢!

【问题讨论】:

  • @CaiusJard - 错误:函数转换(字符不同,未知,未知)不存在
  • 嗯,奇怪。我将server_encoding 设置为UTF8lc_collatelc_ctype 设置为de_DE.UTF-8,我得到SELECT similarity('כפיר','כפיר') 的1。我在 Linux 上运行。

标签: string postgresql utf-8 ascii similarity


【解决方案1】:

好的,所以解决方案很简单。

需要将其转换为字节数组 (bytea),然后再转换回文本。 关于正则表达式替换,我应该使用我想要删除的特定字符而不是使用\W+

所以我的情况的解决方案是:

   select
  similarity(convert(unaccent(regexp_replace(lower('string'), '[.,''׳`"-]', '', 'g'))::bytea,'UTF8','ISO_8859_8')::text,
             convert(unaccent(regexp_replace(lower('string'), '[.,''׳`"-]', '', 'g'))::bytea,'UTF8','ISO_8859_8')::text)

【讨论】:

    猜你喜欢
    • 2018-01-26
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2016-07-15
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多