【发布时间】:2012-05-01 12:22:54
【问题描述】:
背景
用户可以输入名称,系统应该匹配文本,即使用户输入或数据库字段包含重音 (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
【问题讨论】:
-
您的所有搜索都被锚定了吗?如果是这样,旧的
LIKE将与使用text_pattern_ops的索引(以及您的 unaccent 函数)相结合,为您提供很好的服务。我写了more about that here。另外,你知道PostgreSQL unaccent module吗? -
为什么你在没有重音的文字上使用 unaccent,而不是包含重音的列?我希望你在定义索引时也使用了 unaccent 函数。如果是这样,它不会认为在搜索条件上不使用相同的函数就可以使用索引。
-
搜索没有被锚定。我不知道 unaccent 模块。我会研究不重音索引。我打错了
unaccent电话,失败的解决方案现在反映了现实。 -
这个问题似乎离题了,因为它更适合dba.stackexchange.com。
标签: postgresql utf-8 plpgsql string-comparison similarity