postgresql - 自动完成字段的类似 UTF-8 字符串

标签 postgresql utf-8 plpgsql string-comparison similarity

背景

用户可以输入名称,系统应该匹配文本,即使用户输入或数据库字段包含重音 (UTF-8) 字符。这是使用 pg_trgm 模块。

问题

代码类似于以下内容:

  SELECT
    t.label
  FROM
    the_table t
  WHERE
    label % 'fil'
  ORDER BY
    similarity( t.label, 'fil' ) DESC

当用户键入 fil 时,查询匹配 filbert 但不匹配 filé powder。 (因为重音字符?)

失败的解决方案 #1

我尝试实现一个 unaccent 函数并将查询重写为:

  SELECT
    t.label
  FROM
    the_table t
  WHERE
    unaccent( label ) % unaccent( 'fil' )
  ORDER BY
    similarity( unaccent( t.label ), unaccent( 'fil' ) ) DESC

这只返回 filbert

失败的解决方案 #2

按照建议:

CREATE EXTENSION pg_trgm;
CREATE EXTENSION unaccent;

CREATE OR REPLACE FUNCTION unaccent_text(text)
  RETURNS text AS
$BODY$
  SELECT unaccent($1); 
$BODY$
  LANGUAGE sql IMMUTABLE
  COST 1;

表上的所有其他索引都已删除。然后:

CREATE INDEX label_unaccent_idx 
ON the_table( lower( unaccent_text( label ) ) );

这只返回一个结果:

  SELECT
    t.label
  FROM
    the_table t
  WHERE
    label % 'fil'
  ORDER BY
    similarity( t.label, 'fil' ) DESC

问题

重写查询以确保返回两个结果的最佳方法是什么?

谢谢!

相关

http://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.0#Unaccent_filtering_dictionary

http://postgresql.1045698.n5.nabble.com/index-refuses-to-build-td5108810.html

最佳答案

您没有使用 pg_trgm 模块提供的运算符类。创建这样的索引:

CREATE INDEX label_Lower_unaccent_trgm_idx
ON test_trgm USING gist (lower(unaccent_text(label)) gist_trgm_ops);

最初,我在这里有一个 GIN 索引,但 GiST 通常更适合这种查询,因为它可以返回按相似性排序的值。见:

您的查询必须匹配索引表达式才能使用它。

SELECT label
FROM   the_table
WHERE  lower(unaccent_text(label)) % 'fil'
ORDER  BY similarity(label, 'fil') DESC;  -- ok to use original string here

但是,根据 % 运算符,“filbert”和“filé powder”实际上与“fil”并不十分相似。我怀疑你真的想要:

SELECT label
FROM   the_table
WHERE  lower(unaccent_text(label)) LIKE 'fil%'  -- !
ORDER  BY similarity(label, 'fil') DESC;  -- ok to use original string here

这会找到所有以搜索字符串开头的字符串,并首先根据 % 运算符对最佳匹配项进行排序。

从 PostgreSQL 9.1 开始,表达式可以使用 GIN 或 GiST 索引! The manual :

Beginning in PostgreSQL 9.1, these index types also support index searches for LIKE and ILIKE, for example

如果您确实打算使用 % 运算符:

尝试 adapting the threshold对于相似性运算符 %:

SET pg_trgm.similarity_threshold = 0.1;  -- Postgres 9.6 or later
SELECT set_limit(0.1);  -- Postgres 9.5 or older

或者更低?默认值为 0.3。只是为了查看阈值是否过滤了额外的匹配项。

关于postgresql - 自动完成字段的类似 UTF-8 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10237366/

相关文章:

postgresql - 连接到 PostgreSQL : Postico and TablePlus DB GUIs can't connect but `psql` in Docker works (FATAL: password authentication failed for user)

c++ - Windows UTF8 到 UTF16

sql - 从 PostgreSQL 中的搜索中排除过时数据的最佳方法

postgresql - 如何避免在 PostgreSQL 9.2.1 中循环触发调用

postgresql - 如何将我的 Rails 数据类型更改为 PostGres bigint?

postgresql - 如果将时间戳转换为日期,Postgres 是否使用索引?

postgresql - 使用 play-slick 时与 heroku postgres 的间歇性连接失败

php - utf-8的问题

javascript - eclipse : can't remove default encoding for javascript and json

sql - 为什么 PL/pgSQL 函数可以有副作用,而 SQL 函数不能?