我正在开发在 Postgres 数据库中按名称搜索实体的功能。名称通常由 1-3 个单词组成,可能包含 &、!、(、)、- 等符号。 我正在使用杜松子酒三元组索引和查询:
WHERE name ILIKE '%something%', ILIKE 'a%'
和WHERE name % 'abc'
进行模糊搜索(如果通过ILIKE没有找到任何精确匹配)。
问题是我们需要支持任何字符的搜索,而不仅仅是字母和数字。 Trigram 索引会忽略此类字符。
我已经尝试过使用
text_pattern_ops
索引来解决这种情况,但没有成功:诸如 WHERE name ILIKE '%$%'
之类的查询非常慢:(
那么,有什么方法可以高效处理此类查询呢?为此我需要进行全文搜索吗? 谢谢!
更新:
表格如下:
id(整数) | 姓名(文字) |
---|---|
123 | 杜嘉班纳 |
查询如下:
SELECT name FROM brand WHERE name ILIKE '%&%' ORDER BY name;
UPD2:
EXPLAIN(analyze, verbose, buffers, settings) SELECT name FROM brand WHERE name ILIKE '%$%' ORDER BY name
的查询计划:
索引创建为:
CREATE INDEX brand_trgm_idx ON brand USING gin (name gin_trgm_ops);
表创建为:
CREATE TABLE brand
(
id serial PRIMARY KEY,
name TEXT,
collection_id TEXT,
created_at TIMESTAMP DEFAULT now() NOT NULL,
created_by TEXT NOT NULL
);
还尝试过:
CREATE INDEX brand_name_idx ON brand (name text_pattern_ops);
trgm.h 可以实现
#define KEEPONLYALNUM
。如果您删除它并重新编译,它将保留除空格之外的标点符号。然而,“%$%”中没有任何可用的三元组,就像“%a%”一样,因为它太短了。因此,您向我们展示的一个具体示例仍然不会使用索引。
这样做也相当危险,因为升级系统可能会导致更改的二进制文件悄然丢失。最好分叉并重命名,但这需要大量工作。