PostgreSQL 重音 + 不区分大小写的搜索
PostgreSQL accent + case insensitive search
我正在寻找一种方法来支持不区分大小写 + 重音不区分搜索的良好性能。到目前为止,我们在使用 MSSql 服务器上没有问题,在 Oracle 上我们必须使用 OracleText
,现在我们在 PostgreSQL 上需要它。
我已经找到了 this post,但我们需要将它与不区分大小写结合起来。我们还需要使用索引,否则性能可能会受到影响。
关于大型数据库的最佳方法的任何实际经验?
如果您需要“不区分大小写”,有多种选择,具体取决于您的具体要求。
也许最简单,使表达式索引不区分大小写。
基于参考答案中列出的函数 f_unaccent()
:
- Does PostgreSQL support "accent insensitive" collations?
CREATE INDEX users_lower_unaccent_name_idx ON users(<b>lower(</b>f_unaccent(name)<b>)</b>);
然后:
SELECT *
FROM users
WHERE lower(f_unaccent(name)) = lower(f_unaccent('João'));
或 你可以将 lower()
构建到函数 f_unaccent()
中,以导出类似 f_lower_unaccent()
.
的东西
或(特别是如果你无论如何都需要进行模糊模式匹配)你可以使用附加模块 pg_trgm
提供的三元组索引建立在上述功能之上,它还支持 ILIKE
。详情:
- LOWER LIKE vs iLIKE
我在 referenced answer 中添加了注释。
或你可以使用附加模块citext
(但我宁愿避免它):
- Deferrable, case-insensitive unique constraint
不区分大小写的全文搜索词典
FTS is naturally case-insensitive by default,
Converting tokens into lexemes. A lexeme is a string, just like a token, but it has been normalized so that different forms of the same word are made alike. For example, normalization almost always includes folding upper-case letters to lower-case, and often involves removal of suffixes (such as s or es in English).
您还可以使用 unaccent
、
定义自己的字典
CREATE EXTENSION unaccent;
CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
ALTER TEXT SEARCH CONFIGURATION mydict
ALTER MAPPING FOR hword, hword_part, word
WITH unaccent, simple;
然后您可以使用功能索引对其进行索引,
-- Just some sample data...
CREATE TABLE myTable ( myCol )
AS VALUES ('fóó bar baz'),('qux quz');
-- No index required, but feel free to create one
CREATE INDEX ON myTable
USING GIST (to_tsvector('mydict', myCol));
现在可以很简单的查询了
SELECT *
FROM myTable
WHERE to_tsvector('mydict', myCol) @@ 'foo & bar'
mycol
-------------
fóó bar baz
(1 row)
另见
我正在寻找一种方法来支持不区分大小写 + 重音不区分搜索的良好性能。到目前为止,我们在使用 MSSql 服务器上没有问题,在 Oracle 上我们必须使用 OracleText
,现在我们在 PostgreSQL 上需要它。
我已经找到了 this post,但我们需要将它与不区分大小写结合起来。我们还需要使用索引,否则性能可能会受到影响。 关于大型数据库的最佳方法的任何实际经验?
如果您需要“不区分大小写”,有多种选择,具体取决于您的具体要求。
也许最简单,使表达式索引不区分大小写。
基于参考答案中列出的函数 f_unaccent()
:
- Does PostgreSQL support "accent insensitive" collations?
CREATE INDEX users_lower_unaccent_name_idx ON users(<b>lower(</b>f_unaccent(name)<b>)</b>);
然后:
SELECT *
FROM users
WHERE lower(f_unaccent(name)) = lower(f_unaccent('João'));
或 你可以将 lower()
构建到函数 f_unaccent()
中,以导出类似 f_lower_unaccent()
.
或(特别是如果你无论如何都需要进行模糊模式匹配)你可以使用附加模块 pg_trgm
提供的三元组索引建立在上述功能之上,它还支持 ILIKE
。详情:
- LOWER LIKE vs iLIKE
我在 referenced answer 中添加了注释。
或你可以使用附加模块citext
(但我宁愿避免它):
- Deferrable, case-insensitive unique constraint
不区分大小写的全文搜索词典
FTS is naturally case-insensitive by default,
Converting tokens into lexemes. A lexeme is a string, just like a token, but it has been normalized so that different forms of the same word are made alike. For example, normalization almost always includes folding upper-case letters to lower-case, and often involves removal of suffixes (such as s or es in English).
您还可以使用 unaccent
、
CREATE EXTENSION unaccent;
CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
ALTER TEXT SEARCH CONFIGURATION mydict
ALTER MAPPING FOR hword, hword_part, word
WITH unaccent, simple;
然后您可以使用功能索引对其进行索引,
-- Just some sample data...
CREATE TABLE myTable ( myCol )
AS VALUES ('fóó bar baz'),('qux quz');
-- No index required, but feel free to create one
CREATE INDEX ON myTable
USING GIST (to_tsvector('mydict', myCol));
现在可以很简单的查询了
SELECT *
FROM myTable
WHERE to_tsvector('mydict', myCol) @@ 'foo & bar'
mycol
-------------
fóó bar baz
(1 row)
另见