Фон
Пользователи могут вводить имя, и система должна соответствовать тексту, даже если пользовательский ввод или поле базы данных содержат символы с акцентом (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