本节介绍附加函数和操作符,它们与文本搜索非常有用。
第 12.3.1 节 展示了如何将原始文本文档转换成 tsvector
值。PostgreSQL 还提供了可用于处理已处于 tsvector
形式的文档的函数和运算符。
tsvector
|| tsvector
tsvector
连接运算符返回一个向量,该向量将作为参数给出的两个向量的词素和位置信息合并起来。连接期间将保留位置和权重标签。出现在右侧向量的各个位置都会因左侧向量中提到的最大位置而产生偏移,以便结果几乎等同于对两个原始文档字符串的连接执行 to_tsvector
的结果。(这种等价性并不完全准确,因为从左侧参数末尾移除的任何停用词都不会影响结果,但如果使用文本连接,则它们会影响右侧参数中词素的位置。)
使用向量形式的连接(而不是先连接文本再应用 to_tsvector
)的一大优势在于,您可以使用不同的配置来解析文档的不同部分。此外,由于 setweight
函数对给定向量的所有词素都用相同的方式进行标记,因此如果您希望以不同的权重标记文档的不同部分,则在连接之前解析文本并执行 setweight
是必要的。
setweight(vector
tsvector
, weight
"char"
) 返回 tsvector
setweight
返回输入向量的副本,在其中每个位置都已使用给定的 weight
进行标记,该值可以是 A
、B
、C
或 D
。(D
是新向量的默认值,因此不会显示在输出中。)连接向量时保留这些标签,从而允许对来自文档不同部分的词语按不同权重进行排名功能加权。
请注意,权重标签适用于 各个位置,而不是 词素。如果输入向量已去除位置,则 setweight
不执行任何操作。
length(vector
tsvector
) 返回 integer
返回存储在向量中的词素数量。
strip(vector
tsvector
) 返回 tsvector
返回一个向量,其中列出了与给定向量相同的词素,但缺少任何位置或权重信息。结果通常比未剥离的向量小很多,但它也减少了实用性。未剥离向量上的相关性排名高于已剥离向量。此外,<->
(跟随)tsquery
运算符永远不会匹配已剥离的输入,因为它无法确定词素出现之间的距离。
tsvector
相关函数的完整列表可在 表 9.43 中获得。
第 12.3.2 节 展示了如何将原始文本查询转换为tsquery
值。PostgreSQL还提供函数和运算符,可用于操作已采用tsquery
形式的查询。
tsquery
&& tsquery
返回两个给定查询的 AND 组合。
tsquery
|| tsquery
返回两个给定查询的 OR 组合。
!! tsquery
返回给定查询的否定(NOT)。
tsquery
<-> tsquery
返回查询,该查询使用<->
(FOLLOWED BY)tsquery
运算符搜索与第一个给定查询匹配,然后立即匹配与第二个给定查询匹配。例如
SELECT to_tsquery('fat') <-> to_tsquery('cat | rat'); ?column? ---------------------------- 'fat' <-> ( 'cat' | 'rat' )
tsquery_phrase(query1
tsquery
, query2
tsquery
[, distance
integer
]) 返回 tsquery
返回查询,该查询使用<
N
>tsquery
运算符搜索与第一个给定查询匹配,然后按正好为distance
词素的距离与第二个给定查询匹配。例如
SELECT tsquery_phrase(to_tsquery('fat'), to_tsquery('cat'), 10); tsquery_phrase ------------------ 'fat' <10> 'cat'
numnode(query
tsquery
) 返回 integer
返回tsquery
中的节点数(词素加运算符)。此函数对于确定query
是否有意义(返回 > 0)或仅包含停用词(返回 0)非常有用。示例
SELECT numnode(plainto_tsquery('the any')); NOTICE: query contains only stopword(s) or doesn't contain lexeme(s), ignored numnode --------- 0 SELECT numnode('foo & bar'::tsquery); numnode --------- 3
querytree(query
tsquery
) 返回 text
返回可用于检索索引的 tsquery
部分。此函数可用于检测无法建立索引的查询,例如只含有停止词或只含有否定项的查询。例如
SELECT querytree(to_tsquery('defined')); querytree ----------- 'defin' SELECT querytree(to_tsquery('!defined')); querytree ----------- T
ts_rewrite
函数系列搜索给定的 tsquery
中目标子查询的出现情况,并用替代子查询替换每个出现情况。从本质上来说,该操作是 tsquery
特定的子字符串替换版本。目标和替代表现形式可以看作 查询重写规则。这组此类重写规则可以是一种强大的搜索帮助。例如,你可以使用同义词(例如,new york
、big apple
、nyc
、gotham
)展开搜索,也可以缩小搜索范围,将用户引导到某些热门话题。此功能与同义词词典(第 12.6.4 节)在功能上有一定的重叠。但是,你可以随时修改一组重写规则而无需重新建立索引,而更新同义词词典需要重新建立索引才能生效。
ts_rewrite (query
tsquery
, target
tsquery
, substitute
tsquery
) 返回 tsquery
此形式的 ts_rewrite
仅仅应用一条重写规则:target
以 substitute
替换 query
中的任何出现情况。例如
SELECT ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'c'::tsquery); ts_rewrite ------------ 'b' & 'c'
ts_rewrite (query
tsquery
, select
text
) 返回 tsquery
此形式的 ts_rewrite
接受一个开始 query
和一个 SQL select
命令,后者提供为文本字符串。该 select
必须生成两列 tsquery
类型的列。对于 select
结果的每行,第一个列值(目标)的出现情况将在当前 query
值中被第二个列值(替代)替换。例如
CREATE TABLE aliases (t tsquery PRIMARY KEY, s tsquery); INSERT INTO aliases VALUES('a', 'c'); SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases'); ts_rewrite ------------ 'b' & 'c'
请注意,当以这种方式应用多条重写规则时,应用顺序非常重要;因此实际上你会希望源查询 ORDER BY
某种排序键。
让我们思考一个现实生活中的天文示例。我们将使用表驱动的重写规则来展开查询 supernovae
CREATE TABLE aliases (t tsquery primary key, s tsquery); INSERT INTO aliases VALUES(to_tsquery('supernovae'), to_tsquery('supernovae|sn')); SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases'); ts_rewrite --------------------------------- 'crab' & ( 'supernova' | 'sn' )
我们只需要更新表格即可更改重写规则
UPDATE aliases SET s = to_tsquery('supernovae|sn & !nebulae') WHERE t = to_tsquery('supernovae'); SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases'); ts_rewrite --------------------------------------------- 'crab' & ( 'supernova' | 'sn' & !'nebula' )
当重写规则较多时,重写会很慢,因为它检查每个规则是否可能匹配。为了过滤掉显而易见的非候选规则,我们可以使用 tsquery
类型的包含运算符。在以下示例中,我们只选择那些可能与原始查询相匹配的规则
SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases WHERE ''a & b''::tsquery @> t'); ts_rewrite ------------ 'b' & 'c'
此部分中描述的方法已被存储生成的列所淘汰,如 第 12.2.2 节 中所述。
在将一个单独的列用于存储文档的 tsvector
表示时,需要创建一个触发器,以便在文档内容列发生更改时更新 tsvector
列。为此,提供了两个内置触发器函数,您也可以编写自己的函数。
tsvector_update_trigger(tsvector_column_name
,config_name
,text_column_name
[, ... ]) tsvector_update_trigger_column(tsvector_column_name
,config_column_name
,text_column_name
[, ... ])
这些触发器函数可自动根据 CREATE TRIGGER
命令中指定的参数,根据一个或多个文本列计算 tsvector
列。以下是它们的用法示例
CREATE TABLE messages ( title text, body text, tsv tsvector ); CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON messages FOR EACH ROW EXECUTE FUNCTION tsvector_update_trigger(tsv, 'pg_catalog.english', title, body); INSERT INTO messages VALUES('title here', 'the body text is here'); SELECT * FROM messages; title | body | tsv ------------+-----------------------+---------------------------- title here | the body text is here | 'bodi':4 'text':5 'titl':1 SELECT title, body FROM messages WHERE tsv @@ to_tsquery('title & body'); title | body ------------+----------------------- title here | the body text is here
创建此触发器后,title
或 body
的任何更改都会自动反映到 tsv
中,而无需应用程序担心这一点。
第一个触发器参数必须是要更新的 tsvector
列的名称。第二个参数指定用于执行转换的文本搜索配置。对于 tsvector_update_trigger
,配置名称只需作为第二个触发器参数给出即可。它必须像上面显示的那样具有 schema 限定,以便在 search_path
发生更改时触发器行为不会发生更改。对于 tsvector_update_trigger_column
,第二个触发器参数是另一表列的名称,它必须是 regconfig
类型。这允许按行选择配置。其余参数是文本列的名称(text
、varchar
或 char
类型)。这些将按给定的顺序包含在文档中。NULL 值将被跳过(但其他列仍将被索引)。
这些内置触发器的一个限制是它们将所有输入列视为相同。如需以不同方式处理列(例如,为标题加权不同于正文),则需要编写自定义触发器。以下是一个以 PL/pgSQL 作为触发器语言的示例
CREATE FUNCTION messages_trigger() RETURNS trigger AS $$ begin new.tsv := setweight(to_tsvector('pg_catalog.english', coalesce(new.title,'')), 'A') || setweight(to_tsvector('pg_catalog.english', coalesce(new.body,'')), 'D'); return new; end $$ LANGUAGE plpgsql; CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON messages FOR EACH ROW EXECUTE FUNCTION messages_trigger();
请记住,在触发器中创建 tsvector
值时,显式指定配置名称很重要,以便列内容不会受到 default_text_search_config
更改的影响。如果不这样做,可能会导致问题,例如转储和还原后搜索结果发生更改。
函数 ts_stat
可用于检查您的配置和查找停用词候选。
ts_stat(sqlquery
text
, [weights
text
, ] OUTword
text
, OUTndoc
integer
, OUTnentry
integer
) returnssetof record
sqlquery
是一个文本值,包含一个 SQL 查询,该查询必须返回一个单一的 tsvector
列。 ts_stat
执行查询并返回 tsvector
数据中包含的每个不同的词素(单词)的统计信息。返回的列为
word
text
— 词素的值
ndoc
integer
— 该单词所在的文档(tsvector
)数
nentry
integer
— 该单词总共出现的次数
如果提供了 weights
,则只计算具有这些权重之一的出现次数。
例如,查找文档集合中最频繁出现的十个单词
SELECT * FROM ts_stat('SELECT vector FROM apod') ORDER BY nentry DESC, ndoc DESC, word LIMIT 10;
同样地,只计算具有权重 A
或 B
的单词出现次数
SELECT * FROM ts_stat('SELECT vector FROM apod', 'ab') ORDER BY nentry DESC, ndoc DESC, word LIMIT 10;
如果您在文档中看到信息不正确、与您对特定功能的体验不符或需要进一步说明,请使用 此表单 报告文档问题。