Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

12.2. 表和索引 #

12.2.1. 搜索表
12.2.2. 创建索引

上一节列举的示例通过使用简单的常量字符串说明了全文匹配。本节将阐述如何搜索表数据,此操作可以选择使用索引。

12.2.2. 创建索引 #

我们创建一个GIN索引(第 12.9 节)以加快文本搜索

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', body));

注意,使用了 to_tsvector 的双参数版本。只有指定配置名称的文本搜索函数才能在表达式索引(第 11.7 节)中使用。这是因为索引内容不能受 default_text_search_config 影响。如果它们受到影响,索引内容可能不一致,因为不同的条目可能包含使用不同的文本搜索配置创建的 tsvector,并且没有任何办法可以猜测哪一个是什么。正确转储和恢复这样的索引是不可能的。

因为在上述索引中使用了 to_tsvector 的双参数版本,所以只有使用与相同配置名称的 to_tsvector 双参数版本的查询引用才会使用该索引。也就是说,WHERE to_tsvector('english', body) @@ 'a & b' 可以使用该索引,但 WHERE to_tsvector(body) @@ 'a & b' 不能。这可确保仅将索引与用于创建索引条目的配置一起使用。

可以设置更复杂的表达式索引,其中配置名称由另一列指定,例如

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(config_name, body));

其中 config_namepgweb 表中的一列。这允许同一索引中的混合配置同时记录对每个索引条目的配置。例如,如果文档集合中包含不同语言的文档,这将很有用。同样,必须将旨在使用索引的查询表述成匹配项,例如 WHERE to_tsvector(config_name, body) @@ 'a & b'

索引甚至可以连接列

CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', title || ' ' || body));

另一种方法是创建一个独立的 tsvector 列来保存 to_tsvector 的输出。要使此列与其源数据保持自动更新,请使用存储的生成列。本示例连接了 titlebody,并使用 coalesce 来确保在另一个字段为 NULL 时仍对一个字段进行索引

ALTER TABLE pgweb
    ADD COLUMN textsearchable_index_col tsvector
               GENERATED ALWAYS AS (to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''))) STORED;

然后我们创建一个GIN索引加快搜索

CREATE INDEX textsearch_idx ON pgweb USING GIN (textsearchable_index_col);

现在,我们已做好执行快速的全文搜索的准备

SELECT title
FROM pgweb
WHERE textsearchable_index_col @@ to_tsquery('create & table')
ORDER BY last_mod_date DESC
LIMIT 10;

分离列方法比表达式索引的一个优点是,无需在查询中明确指定文本搜索配置,以便利用该索引。如上例所示,查询可以依赖于 default_text_search_config。另一个优点是,搜索将会加快速度,因为无需重做 to_tsvector 调用来验证索引匹配。(使用 GiST 索引比使用 GIN 索引时这一点更为重要;请参阅第 12.9 节。)不过,表达式索引方法的设置更简单,所需的磁盘空间也更少,因为 tsvector 表示形式并未明确存储。