PostgreSQL 10.1 手册_部分 II. SQL 语言_第 12 章 全文搜索_12.1. 介绍

简介: 12.1. 介绍 12.1.1. 什么是一个文档? 12.1.2. 基本文本匹配 12.1.3. 配置 全文搜索(或者文本搜索)提供了确定满足一个查询的自然语言文档的能力,并可以选择将它们按照与查询的相关度排序。

12.1. 介绍

全文搜索(或者文本搜索)提供了确定满足一个查询的自然语言文档的能力,并可以选择将它们按照与查询的相关度排序。最常用的搜索类型是找到所有包含给定查询词的文档并按照它们与查询的相似性顺序返回它们。查询相似性的概念非常灵活并且依赖于特定的应用。最简单的搜索认为查询是一组词而相似性是查询词在文档中的频度。

文本搜索操作符已经在数据库中存在很多年了。PostgreSQL对文本数据类型提供了~~*LIKEILIKE操作符,但是它们缺少现代信息系统所要求的很多基本属性:

  • 即使对英语也缺乏语言的支持。正则表达式是不够的,因为它们不能很容易地处理派生词,例如satisfiessatisfy。你可能会错过包含satisfies的文档,尽管你可能想要在对于satisfy的搜索中找到它们。可以使用OR来搜索多个派生形式,但是这样做太罗嗦也容易出错(有些词可能有数千种派生)。

  • 它们不提供对搜索结果的排序(排名),这使它们面对数以千计被找到的文档时变得无效。

  • 它们很慢因为没有索引支持,因此它们必须为每次搜索处理所有的文档。

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

  • 将文档解析成记号。标识出多种类型的记号是有所帮助的,例如数字、词、复杂的词、电子邮件地址,这样它们可以被以不同的方式处理。原则上记号分类取决于相关的应用,但是对于大部分目的都可以使用一套预定义的分类。PostgreSQL使用一个解析器来执行这个步骤。其中提供了一个标准的解析器,并且为特定的需要也可以创建定制的解析器。

  • 将记号转换成词位。和一个记号一样,一个词位是一个字符串,但是它已经被正规化,这样同一个词的不同形式被变成一样。例如,正规化几乎总是包括将大写字母转换成小写形式,并且经常涉及移除后缀(例如英语中的ses)。这允许搜索找到同一个词的变体形式,而不需要冗长地输入所有可能的变体。此外,这个步骤通常会消除停用词,它们是那些太普通的词,它们对于搜索是无用的(简而言之,记号是文档文本的原始片段,而词位是那些被认为对索引和搜索有用的词)。PostgreSQL使用词典来执行这个步骤。已经提供了多种标准词典,并且为特定的需要也可以创建定制的词典。

  • 为搜索优化存储预处理好的文档。例如,每一个文档可以被表示为正规化的词位的一个有序数组。与词位一起,通常还想要存储用于近似排名的位置信息,这样一个包含查询词更密集区域的文档要比那些包含分散的查询词的文档有更高的排名。

词典允许对记号如何被正规化进行细粒度的控制。使用合适的词典,你可以:

  • 定义不应该被索引的停用词。

  • 使用Ispell把同义词映射到一个单一词。

  • 使用一个分类词典把短语映射到一个单一词。

  • 使用一个Ispell词典把一个词的不同变体映射到一种规范的形式。

  • 使用Snowball词干分析器规则将一个词的不同变体映射到一种规范的形式。

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

12.1.1. 什么是一个文档?

一个document是在一个全文搜索系统中进行搜索的单元,例如,一篇杂志文章或电子邮件消息。文本搜索引擎必须能够解析文档并存储词位(关键词)与它们的父文档之间的关联。随后,这些关联会被用来搜索包含查询词的文档。

对于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(文档)匹配一个tsquery(查询)时返回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 以及 FOLLOWED BY 操作符结合多个术语 (语法细节请见第 8.11.2 节)。有几个函数to_tsqueryplainto_tsquery以及phraseto_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输出,它允许在简单情况下跳过从文本字符串到tsvectortsquery的显式转换。可用的变体是:

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

前两种我们已经见过。形式text @@ tsquery等价于to_tsvector(x) @@ y。形式text @@ text等价于to_tsvector(x) @@ plainto_tsquery(y)

tsquery中,&(AND)操作符指定它的两个参数都必须出现在文档中才表示匹配。类似地,|(OR)操作符指定至少一个参数必须出现,而!(NOT)操作符指定它的参数出现才能匹配。 例如,查询fat & ! rat匹配包含fat但是不包含 rat的文档。

<->(FOLLOWED BY) tsquery操作符的帮助下搜索可能的短语,只有该操作符的参数的匹配是相邻的并且符合给定顺序时,该操作符才算是匹配。例如:

SELECT to_tsvector('fatal error') @@ to_tsquery('fatal <-> error');
 ?column? 
----------
 t

SELECT to_tsvector('error is not fatal') @@ to_tsquery('fatal <-> error');
 ?column? 
----------
 f

FOLLOWED BY 操作符还有一种更一般的版本,形式是<N>,其中N是一个表示匹配词位位置之间的差。<1><->相同,而<2>允许刚好一个其他词位出现在匹配之间,以此类推。当有些词是停用词时,phraseto_tsquery函数利用这个操作符来构造一个能够匹配多词短语的tsquery。例如:

SELECT phraseto_tsquery('cats ate rats');
       phraseto_tsquery        
-------------------------------
 'cat' <-> 'ate' <-> 'rat'

SELECT phraseto_tsquery('the cats ate the rats');
       phraseto_tsquery        
-------------------------------
 'cat' <-> 'ate' <2> 'rat'

一种有时候有用的特殊情况是,<0>可以被用来要求两个匹配同一个词的模式。

圆括号可以被用来控制tsquery操作符的嵌套。如果没有圆括号,|的计算优先级最低,然后从低到高依次是&<->!

值得注意的是,AND/OR/NOT运算符意味着当它们在FOLLOWED BY运算符的参数范围内, 与它们没有在范围内的时候有细微的不同,因为在FOLLOWED BY中,匹配的确切位置是很重要的。 例如,通常!x仅匹配不包含x的文档。但是,如果不是紧跟在x之后, 那么!x <-> y匹配y;文档中其他地方出现的x并不妨碍匹配。 另一个例子是x & y通常只要求xy都出现在文档的某处, 但是(x & y) <-> z要求xy匹配在z 之前的相同位置。因此,这个查询的行为不同于x <-> z & y <-> z, 它将与包含两个单独的序列x zy z的文档相匹配。 (由于xy无法在相同位置匹配,因此此特定查询没有任何用处; 但是在更复杂的情况下(如前缀匹配模式),此形式的查询可能会有用。)

12.1.3. 配置

前述的都是简单的文本搜索例子。正如前面所提到的,全文搜索功能包括做更多事情的能力:跳过索引特定词(停用词)、处理同义词并使用更高级的解析,例如基于空白之外的解析。这个功能由文本搜索配置控制。PostgreSQL中有多种语言的预定义配置,并且你可以很容易地创建你自己的配置(psql\dF命令显示所有可用的配置)。

在安装期间一个合适的配置将被选择并且default_text_search_config也被相应地设置在postgresql.conf中。如果你正在对整个集簇使用相同的文本搜索配置,你可以使用在postgresql.conf中使用该值。要在集簇中使用不同的配置但是在任何一个数据库内部使用同一种配置,使用ALTER DATABASE ... SET。否则,你可以在每个会话中设置default_text_search_config

依赖一个配置的每一个文本搜索函数都有一个可选的regconfig参数,因此要使用的配置可以被显式指定。只有当这个参数被忽略时,default_text_search_config才被使用。

为了让建立自定义文本搜索配置更容易,一个配置可以从更简单的数据库对象来建立。PostgreSQL的文本搜索功能提供了四类配置相关的数据库对象:

  • 文本搜索解析器将文档拆分成记号并分类每个记号(例如,作为词或者数字)。

  • 文本搜索词典将记号转变成正规化的形式并拒绝停用词。

  • 文本搜索模板提供位于词典底层的函数(一个词典简单地指定一个模板和一组用于模板的参数)。

  • 文本搜索配置选择一个解析器和一组用于将解析器产生的记号正规化的词典。

文本搜索解析器和模板是从低层 C 函数构建而来,因此它要求 C 编程能力来开发新的解析器和模板,并且还需要超级用户权限来把它们安装到一个数据库中(在PostgreSQL发布的contrib/区域中有一些附加的解析器和模板的例子)。由于词典和配置只是对底层解析器和模板的参数化和连接,不需要特殊的权限来创建一个新词典或配置。创建定制词典和配置的例子将在本章稍后的部分给出。

本文转自PostgreSQL中文社区,原文链接:12.1. 介绍

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
5月前
|
SQL 数据管理 关系型数据库
SQL 语言入门:开启数据管理的大门
在数字化时代,数据已成为核心资产,而 SQL 作为操作关系型数据库的标准语言,是数据从业者、程序员及办公人员必备技能。本文从基础概念讲起,详解 SQL 的核心用法,包括数据查询、插入、修改、删除及表结构操作,并通过实例演示帮助读者快速上手。掌握 SQL,不仅能提升数据处理效率,更为深入理解数据管理打下坚实基础。
|
4月前
|
SQL Oracle 关系型数据库
SQL语言小结
针对数据库、表单和数据行的增删改,没有涉及到sql真正的用途也就是查询,sql提供的查询语句的关键字占 sql 语言的一半之多,查询语句还是得单拿出来讲,不然太多了。 因为没有涉及到查询,所以sql的新增和修改都是很笼统的做法,drop、alter drop、delete这些很容易,逻辑性也不强,再次说明sql的真正精髓在于查询,不然为啥叫做结构化查询语言
338 0
|
4月前
|
SQL 关系型数据库 MySQL
(SQL)SQL语言中的查询语句整理
查询语句在sql中占了挺大一部分篇幅,因为在数据库中使用查询语句的次数远多于更新与删除命令。而查询语句比起其他语句要更加的复杂,可因为sql是数据库不可或缺的一部分,所以即使不懂,也必须得弄懂,以上。
318 0
|
关系型数据库 Go 网络安全
go语言中PostgreSQL驱动安装
【11月更文挑战第2天】
677 5
|
11月前
|
SQL 存储 缓存
YashanDB SQL语言
YashanDB SQL语言
|
12月前
|
SQL 数据可视化 IDE
SQL做数据分析的困境,查询语言无法回答的真相
SQL 在简单数据分析任务中表现良好,但面对复杂需求时显得力不从心。例如,统计新用户第二天的留存率或连续活跃用户的计算,SQL 需要嵌套子查询和复杂关联,代码冗长难懂。Python 虽更灵活,但仍需变通思路,复杂度较高。相比之下,SPL(Structured Process Language)语法简洁、支持有序计算和分组子集保留,具备强大的交互性和调试功能,适合处理复杂的深度数据分析任务。SPL 已开源免费,是数据分析师的更好选择。
|
SQL Oracle 关系型数据库
SQL语言的主要标准及其应用技巧
SQL(Structured Query Language)是数据库领域的标准语言,广泛应用于各种数据库管理系统(DBMS)中,如MySQL、Oracle、SQL Server等
480 9
|
SQL 关系型数据库 MySQL
Go语言项目高效对接SQL数据库:实践技巧与方法
在Go语言项目中,与SQL数据库进行对接是一项基础且重要的任务
317 11
|
SQL 关系型数据库 PostgreSQL
PostgreSQL 11 新特性解读 : psql 新增变量记录SQL语句的执行情况和错误
PostgreSQL 11 版本新增加 ERROR、SQLSTATE、ROW_COUNT、LAST_ERROR_MESSAGE、LAST_ERROR_SQLSTATE 五个变量用来记录SQL语句的执行结果状态和错误信息。
4013 2
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")

推荐镜像

更多