控制文本搜索
本文介绍如何创建搜索向量与查询向量,如何对搜索结果进行排序,以及如何在文本搜索结果中高亮显示关键词。
要实现全文搜索,必须有函数将文档转换为 tsvector
,并将用户查询转换为 tsquery
。同时,需要有函数根据相关性对文档排序,以便返回有用的结果。展示结果的可读性也很重要。Apache Cloudberry 提供了以上所有功能的支持。
本文包含以下主题:
解析文档
Apache Cloudberry 提供了 to_tsvector
函数,用于将文档转换为 tsvector
类型。
to_tsvector([<config> regconfig, ] <document> text) returns tsvector
to_tsvector
会将文本文档解析为词元(token),将词元归约为词条(lexeme),并返回一个包含词条及其在文档中位置的 tsvector
。文档会根据指定或默认的文本搜索配置进行处理。以下是一个简单的例子:
SELECT to_tsvector('english', 'a fat cat sat on a mat - it ate a fat rats');
to_tsvector
-----------------------------------------------------
'ate':9 'cat':3 'fat':2,11 'mat':7 'rat':12 'sat':4
从上面的例子可以看出,结果中没有 a
、on
和 it
,而 rats
被还原为 rat
,标点符号 -
被忽略。
to_tsvector
会调用解析器将文档拆分成词元并为每个词元分配一个类型。系统会依次查阅一个词典列表(参见文本搜索词典),这个列表可能根据词元类型而有所不同。第一个识别该词元的词典会返回一个或多个标准化的词条。例如,rats
被还原为 rat
,是因为某个词典识别它是 rat
的复数形式。一些高频词会被识别为停用词(stop words),在搜索中价值不高,因此会被忽略,例如上例中的 a
、on
和 it
。如果没有任何词典识别一个词元, 也会被忽略。例如 -
被忽略,是因为它属于“空格符号(Space symbols)”类型,而这个类型并没有关联任何词典,因此此类词元永远不会被索引。
使用哪个解析器、词典以及要索引哪些类型的词元,取决于所选的文本搜索配置(参见文本搜索配置示例)。同一个数据库中可以有多个不同配置。系统也预设了多种语言的配置。在上面的例子中使用的是默认的英文配置 english
。
可以使用 setweight
函数为 tsvector
中的词条指定一个权重(weight),可选的权重包括 A
、B
、C
和 D
。通常用于标注文档中不同部分的词条,例如将标题(title)和正文(body)分开标记。之后这些权重信息可以用于提升搜索结果的排序质量。
由于 to_tsvector(NULL)
返回的是 NULL
,因此建议在字段可能为 null 时使用 coalesce
。以下是从结构化文档生成 tsvector
的推荐方法:
函数 setweight
可用于为 tsvector
中的词条添加权重标签,权重可以是 A
、B
、C
或 D
。通常用于标记文档中不同部分的词条来源,比如 title
与 body
。这些权重信息可用于后续的搜索结果排序。
由于 to_tsvector(NULL)
会返回 NULL
,因此在字段可能为 null 时建议使用 coalesce
。下面是从结构化文档创建 tsvector
的推荐方法:
UPDATE tt SET ti = setweight(to_tsvector(coalesce(title,'')), 'A')
|| setweight(to_tsvector(coalesce(keyword,'')), 'B')
|| setweight(to_tsvector(coalesce(abstract,'')), 'C')
|| setweight(to_tsvector(coalesce(body,'')), 'D');
在这个例子中,setweight
用于标记每个词条的来源,之后通过 tsvector
拼接运算符 ||
合并这些标记后的 tsvector
值。相关操作的细节参见附加文本搜索功能。
解析查询
Apache Cloudberry 提供了 to_tsquery
、plainto_tsquery
、phraseto_tsquery
和 websearch_to_tsquery
这些函数,用于将查询字符串转换为 tsquery
类型。其中 to_tsquery
功能最强,但对输入格式要求也更严格;websearch_to_tsquery
是 to_tsquery
的简化版,语法更接近常见网页搜索引擎。
to_tsquery([<config> regconfig, ] <querytext> text) returns tsquery
to_tsquery
会将 querytext 转换为 tsquery
值,输入文本必须由词条组成,并用布尔运算符连接:&
(AND)、|
(OR)、!
(NOT)和 <->
(紧邻),可使用括号进行分组。换句话说,输入必须符合 tsquery 的语法规范。不过与基本 tsquery 输入不同的是,to_tsquery
会先使用指定(或默认)配置将每个词规范化为词条(lexeme),并忽略配置中定义的停用词。例如:
SELECT to_tsquery('english', 'The & Fat & Rats');
to_tsquery
---------------
'fat' & 'rat'
就像基本 tsquery
输入那样,也可以为词条指定权重,用于限制匹配特定权重的 tsvector
词条。例如:
SELECT to_tsquery('english', 'Fat | Rats:AB');
to_tsquery
------------------
'fat' | 'rat':AB
此外,可以在词条后添加 *
表示前缀匹配:
SELECT to_tsquery('supern:*A & star:A*B');
to_tsquery
--------------------------
'supern':*A & 'star':*AB
这样的词条会匹配 tsvector
中所有以该前缀开头的词。
to_tsquery
也支持使用单引号括起的短语,这在启用了支持短语的词典(如同义词词典)时很有用。例如,某个同义词词典中包含规则 supernovae stars : sn
,那么:
SELECT to_tsquery('''supernovae stars'' & !crab');
to_tsquery
---------------
'sn' & !'crab'
如果不加引号,像这种没有用运算符连接的多词输入会导致语法错 误。
plainto_tsquery([ <config> regconfig, ] <querytext> text) returns tsquery
plainto_tsquery
用于将普通文本 querytext
转换为 tsquery
。其处理流程类似 to_tsvector
,文本会被解析并规范化,并在剩余词条之间自动插入 &
(AND)运算符。
例如:
SELECT plainto_tsquery('english', 'The Fat Rats');
plainto_tsquery
-----------------
'fat' & 'rat'