上一节中的示例说明了使用简单常量字符串进行全文匹配。本节展示了如何搜索表数据,并可选择使用索引。
可以不使用索引进行全文搜索。一个简单的查询,用于打印在其 body
字段中包含单词 friend
的每一行的 title
,是:
SELECT title FROM pgweb WHERE to_tsvector('english', body) @@ to_tsquery('english', 'friend');
由于所有这些单词都会被简化为相同的规范化词元(lexeme),所以这也将找到相关词,例如 friends
和 friendly
。
上面的查询指定了使用 english
配置来解析和规范化字符串。或者,我们也可以省略配置参数:
SELECT title FROM pgweb WHERE to_tsvector(body) @@ to_tsquery('friend');
此查询将使用由 default_text_search_config 设置的配置。
一个更复杂的例子是选择在 title
或 body
中包含 create
和 table
的十个最新文档:
SELECT title FROM pgweb WHERE to_tsvector(title || ' ' || body) @@ to_tsquery('create & table') ORDER BY last_mod_date DESC LIMIT 10;
为清晰起见,我们省略了 coalesce
函数的调用,而这些调用将需要找到在一个字段中包含 NULL
的行。
尽管这些查询在没有索引的情况下也能工作,但对于大多数应用程序来说,这种方法太慢了,除了偶尔的临时搜索。全文搜索的实际使用通常需要创建索引。
我们可以创建一个GIN索引(第 12.9 节)来加速全文搜索。
CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', body));
请注意,这里使用了 to_tsvector
的 2 参数版本。表达式索引(第 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_name
是 pgweb
表中的一个列。这允许在同一个索引中使用混合配置,同时记录每个索引条目使用的配置。例如,如果文档集合包含不同语言的文档,这将很有用。同样,旨在使用的查询必须符合匹配模式,例如 WHERE to_tsvector(config_name, body) @@ 'a & b'
。
索引甚至可以连接列:
CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', title || ' ' || body));
另一种方法是创建一个单独的 tsvector
列来保存 to_tsvector
的输出。为了使此列与源数据自动保持同步,请使用存储的生成列。此示例连接了 title
和 body
,并使用 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
表示没有显式存储。
如果您在文档中看到任何不正确的地方、与您对特定功能的体验不符或需要进一步澄清的内容,请使用此表单报告文档问题。