12.1. 介绍

全文搜索(或只是文本搜索)提供满足查询的识别自然语言文档的能力, 并且任意地通过相关性查询进行排序。搜索最常见的类型是找到所有包含给定的查询术语的记录,并且以相似性的查 询顺序返回它们。 querysimilarity的概念是非常灵活的,取决于特定的应用。最简单的 搜索认为query是一组词,并且similarity为文档中的查询词出现的频率。

文本搜索操作符已经在数据库中存在多年。PostgreSQL为文本数据类型提供~, ~*, LIKEILIKE操作符,但它们缺乏许多通过现代信息系统要求的必要属性:

全文索引允许文档被预处理,并且为后边的快速搜索保存一个索引。预处理包括:

字典允许细粒度控制如何使用合适的字典规范化标记。你可以:

一种数据类型tsvector用于存储预处理文档,以及类型tsquery 表示处理的查询(第 8.11 节)。 为这些数据类型提供很多的函数和操作符(第 9.13 节),其中最重要的是匹配运算符@@,将在第 12.1.2 节中介绍。 全文搜索可以使用索引进行加速(第 12.9 节)。

12.1.1. 文档是什么?

一个文档是全文搜索系统的搜索单元;例如,杂志上的一篇文章或电子邮件消息。 文本搜索引擎必须能够解析文档,而且可以存储它们父文档词(关键词)的联系性。之后, 这些联系用来搜索包含查询词的文档。

PostgreSQL中搜索,文档通常是一个数据库表中一行的文本字段,或者这些字段的可能组合(级联), 可能存储在多个表中或者动态地获得。换句话说,一个文档可以由索引的不同部分构成,它不可能随时随地作 为一个整体存储。比如:

SELECT title || ' ' ||  author || ' ' ||  abstract || ' ' || body AS document
FROM messages
WHERE mid = 12;

SELECT m.title || ' ' || m.author || ' ' || m.abstract || ' ' || d.body AS document
FROM messages m, docs d
WHERE mid = did AND mid = 12;

注意: 注意:实际上,在这些示例查询中,coalesce使用时应防止一个独立的NULL属性导致整个文档的NULL结果。

另外一个可能性是在文档系统中作为简单的文本文档存储。在这种情况下,数据库可以用于存储全 文索引并且执行搜索,同时使用一些唯一标识从文件系统中检索文档。然而,从外部检索文件,数据库 需要拥有超级用户权限或者特殊函数支持,因此比把所有数据保存在PostgreSQL中相比较, 这往往不太方便。同时,保持所有的数据在数据库里面允许轻松访问文档的元数据以帮助索引和显示。

为了文本搜索目的,每个文档必须减少到预处理tsvector格式。在文档的tsvector表示形式上完整的执行搜索 和排序—当为了显示给用户来选择文档时,只需要检索原文本。因此我们常说的tsvector作为文档,当然它仅仅是 完整文档的一种紧凑表示。

12.1.2. 基本文本匹配

PostgreSQL中的全文搜索基于匹配算子@@,如果一个tsvector(document)匹配一个tsquery(query), 则返回true。不管哪个数据类型先被重写:

SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;
 ?column?
----------
 t

SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector;
 ?column?
----------
 f

正如上面例子表明,一个tsquery不仅仅是原文本,更多的是一个tsvector。一个包含搜索条件的tsquery, 必须是已经标准化的词,并且可能使用AND, OR, 和 NOT操作符连接多个术语(详情请见第 8.11 节)。 函数to_tsqueryplainto_tsquery在将用户书写文本转换成一个合适的tsquery是非常有帮助的。 比如通过标准化文本中的词。类似的,to_tsvector用于解析和标准化文档字符串。因此在实践中文本搜索匹配 可能看起来更像这样:

SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');
 ?column? 
----------
 t

观察这个匹配可能不会成功,如果写成这样:

SELECT 'fat cats ate fat rats'::tsvector @@ to_tsquery('fat & rat');
 ?column? 
----------
 f

由于这儿没有发生词rats的标准化。一个tsvector的元素是词,假设已经被标准化,所以rats不匹配rat

@@操作符也支持text输入,允许一个文本字符串的显示转换为tsvector或者在简单情况下忽略tsquery。 可用形式是:

tsvector @@ tsquery
tsquery  @@ tsvector
text @@ tsquery
text @@ text

我们已经看到了前面两种,形式 text @@ tsquery等价于to_tsvector(x) @@ ytext @@ text等价于 to_tsvector(x) @@ plainto_tsquery(y)

12.1.3. 配置

上面是所有简单文本搜索例子。如前所述,全文搜索功能还有能力做更多事情:忽略索引某个词(干扰词), 过程同义词和使用复杂解析,比如:不仅仅基于空白格的解析。这些功能通过文本搜索配置控制。 PostgreSQL来自多语言的预先定义的配置,并且你也可以很容易的创建你自己的配置(psql\dF 命令显示了 所有可用配置)。

在安装期间选择一个合适的配置,并且在postgresql.conf中相应的设置default_text_search_config。 如果为了整个集群使用同一个文本搜索配置你可以使用postgresql.conf中的值。为了在集群中使用不同配置,但是在任何其他一个数据库的同一 配置中使用ALTER DATABASE ... SET。否则,你可以在每个会话中设置default_text_search_config

每个依赖于配置的文本搜索函数有一个可选的regconfig参数,因此可以明确声明使用的配置。 仅当忽略这些参数的时候,才使用default_text_search_config

为了更方便的建立自定义文本搜索配置,从简单的数据库对象中建立了配置。 PostgreSQL文本搜索功能提供了四种类型的配置相关的数据库对象:

文本搜索解析器和模板是从低层次的C函数建立的;因此它需要C程序能力开发新产品, 并且需要超级用户权限安装到数据库中(在PostgreSQL发布的contrib/范围内有附加解析器和模板的实例)。 因为词典和配置仅仅参数化并且连接到一些潜在的解析器和模板上,创建一个新的词典或者配置不需要特定的权限。 创建自定义词典和配置实例出现在本章节的后面。