假设我有一个以movie
field命名的表name
,即VARCHAR
field。
我想在我的网站中实现一个搜索栏,以便当用户输入字符串时,我可以查询具有该名称的电影。
我的第一种方法很幼稚:
select *
from movie
where name like '%user_string%';
限制是:
我的想法是创建一个附加normalized_name
字段,该name
字段使用去除了所有特殊字符和重音符号的字段进行计算。然后查询将变为:
select *
from movie
where normalized_name like '%user_string%';
例如:用户搜索pokemon
,数据库查询返回带有normalized_name
=的电影pokemon
,真实名称为Pokémon
。显然,用户字符串也将首先进行规范化-以便也允许通过电影真实姓名进行搜索。
现在,这是一种有效的方法吗?什么是最广泛使用的-可能还会使搜索变得更好?有关于这个问题的文献吗?
在该列的精简版本上创建一个三字母索引:
创建必要的扩展并创建一个不可变的unaccent
被称为f_unaccent
(有关更多信息,请参见此处):
CREATE EXTENSION pg_trgm;
CREATE EXTENSION unaccent;
CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
RETURNS text LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
'$libdir/unaccent', 'unaccent_dict';
CREATE OR REPLACE FUNCTION public.f_unaccent(text)
RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
$func$;
在列上创建三元组索引:
CREATE INDEX ON movie USING gin (translate(f_unaccent(name), '''', '') gin_trgm_ops);
现在执行以下查询:
SELECT * FROM movie
WHERE translate(f_unaccent(name), '''', '') ILIKE translate(f_unaccent('user_string'), '''');