全文搜索

本文档介绍全文搜索的基础知识,其在 YMatrix 数据库中的工作原理,并给出示例。

背景

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

  • 缺乏对语言的全面支持(即使对英语也是如此)。只使用正则表达式(包含数字、字母、符号通配符等,如 ^[a-zA-Z0-9_-]{3,15}$)是不够的,因为它们不能很容易地处理派生词,例如 satisfiessatisfy。如果你使用正则表达式搜索 satisfy,则很可能会错过包含 satisfies 的文档。
  • 它们不提供对搜索结果的排序,这使它们面对数以千计被找到的文档时变得无效。
  • 它们很慢因为没有索引支持,因此它们必须为每次搜索处理所有的文档。

为了解决以上问题,全文搜索出现了。

概念

  • 全文搜索和全文索引:全文搜索(或文本搜索)提供了识别能满足查询条件的自然语言文档的能力,并可以将查询结果按照相关度进行排序。它也是处理非结构化数据的一种有效方法。非结构化数据指不定长或无固定格式的数据,如邮件、Word 文档等。基本思路是把非结构化数据变得有结构,即把非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对这些有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,则称之为全文索引。
  • 文档:一个文档是一个全文搜索系统中进行搜索的单元。例如,一篇杂志文章或电子邮件消息。文本搜索引擎必须能够解析文档并存储词位与其父文档之间的关联,然后这些关联会被用来搜索包含查询词的文档。

特点

全文搜索具有以下特点:

  • 更高的精确度:全文搜索提供了比传统搜索算法更高的精确度。它检查每个存储文档中的所有单词,试图匹配搜索条件。
  • 更好的搜索效率:全文搜索通过将问题分为两个任务:索引和搜索,来提高搜索效率。索引阶段扫描所有文档的文本,并建立搜索词列表。
  • 更强的用户体验:全文搜索通过提供更相关的搜索结果来增强用户体验。它可以比简单的抽象搜索揭示更多的信息。
  • 多功能性:全文搜索在许多领域都有应用,包括网站、内容管理系统和文档管理。

原理

全文搜索需要建立全文索引,它允许文档被预处理并且保存一个索引,便于之后快速搜索。预处理包括:

  1. 将文档解析成记号。标识出多种类型的记号是有所帮助的,例如数字、词、复杂的词、电子邮件地址,这样它们可以被以不同的方式处理;

  2. 将记号转换为词位(或关键词)。一个词位是一个被规范化的字符串。规范化包括将大写字母转换为小写、移除英文单词后缀(例如 ses)等。这种处理就允许了用户可以完整地搜索到同一个词的变体形式。简而言之,记号是文档文本的原始片段,而词位是被认为对索引和搜索有用的词;

  3. 存储预处理好的文档,以便优化之后的搜索。每一个经过预处理的文档都包含规范化过的词位的有序数组,以及用于近似排名的位置信息。这样一个包含查询词更『密集』区域的文档要比包含分散查询词的文档有更高的排名,也就是会被『优先展示』。

除索引之外,全文搜索还基于两种数据类型:tsvectortsquery

  • tsvector 用于存储预处理后的文档。
  • tsquery 用于表示处理过的查询。

有很多函数和操作符都可用于这些数据类型,其中最重要的是匹配操作符 @@

示例

注意!
MARS3、MARS2 表均不支持全文搜索。

首先,创建一个名为 articles 的 HEAP 表,其中包含列 idtitlecontent

=# CREATE TABLE articles (
id int,
title text,
content text
)
DISTRIBUTED BY (id);

插入 10 条测试数据。

=# INSERT INTO articles (id, title, content) VALUES
(1, '数据库管理', '数据库管理是一种组织、存储、维护和提取计算机数据库中信息的过程。'),
(2, '数据分析', '数据分析是一种使用统计和计算工具从原始数据中提取有用信息的过程。'),
(3, '机器学习', '机器学习是一种人工智能(AI)形式,它允许计算机无需明确编程即可学习。'),
(4, '深度学习', '深度学习是一种机器学习的方法,它依赖于使用人工神经网络进行模型化决策。'),
(5, '自然语言处理', '自然语言处理是一种使计算机理解、解释和生成人类语言的技术。'),
(6, '计算机视觉', '计算机视觉是一种使计算机能够从图像或多维数据中获取高级理解的科学。'),
(7, '软件工程', '软件工程是一种使用系统化的方法设计、开发和测试软件的应用科学。'),
(8, '网络安全', '网络安全涉及保护计算机系统及其数据,防止未经授权的访问或损害。'),
(9, '云计算', '云计算是一种使用互联网提供按需计算资源和数据的模型。'),
(10, '物联网', '物联网是一种使物理设备通过网络连接并交换数据的系统。');

模糊搜索(非全文搜索)示例

=# SELECT id, title, content
FROM articles
WHERE content like '%机器学习%';
 id |  title   |                                content
----+----------+------------------------------------------------------------------------
  3 | 机器学习 | 机器学习是一种人工智能(AI)形式,它允许计算机无需明确编程即可学习。
  4 | 深度学习 | 深度学习是一种机器学习的方法,它依赖于使用人工神经网络进行模型化决策。
(2 rows)

全文搜索示例

要实现全文搜索必须要运用到两个函数:

  • to_tsquery ( [ config regconfig, ] query text )to_tsquery() 函数将文本转化为 tsquery,即处理过的查询,单词必须由有效的 tsquery 操作符组合。
  • to_tsvector ( [ config regconfig, ] document text )to_tsvector() 函数将文本转化为 tsvector,即预处理过的文档,单词中包含位置信息。

创建一个全文搜索索引。

=# CREATE INDEX articles_content_gin ON articles USING gin(to_tsvector('simple', content));

然后使用这个索引来进行全文搜索。@@ 是一个文本搜索操作符,用于判断前后两个项是否匹配,项的顺序没有影响,结果返回 TRUEFALSE,即匹配或不匹配。

=# SELECT id, title, content
FROM articles
WHERE to_tsvector('simple', content) @@ to_tsquery('simple', '深度学习是一种机器学习的方法');
 id |  title   |                                content
----+----------+------------------------------------------------------------------------
  4 | 深度学习 | 深度学习是一种机器学习的方法,它依赖于使用人工神经网络进行模型化决策。
(1 row)

这是一个全文搜索查询,它做了以下几件事情:

  1. SELECT id, title, content FROM articles 这个部分是标准的 SQL 查询,它从 articles 表中选择了 idtitle,和 content 这三个字段;

  2. WHERE to_tsvector('simple', content) @@ to_tsquery('simple', '深度学习是一种机器学习的方法') 这个部分是全文搜索的条件。这里使用了 YMatrix 的全文搜索功能,来查找 content 字段中包含 深度学习是一种机器学习的方法 的文档。说明:由于本示例的内容是中文,所以需要使用 simple 配置,它不会进行任何语言特定的处理。如果你的文档内容为英文,则可以使用 english

  3. to_tsvector('simple', content) 这个函数将 content 字段的文本转化为一个向量(tsvector),以便进行全文搜索;

  4. to_tsquery('simple', '深度学习是一种机器学习的方法') 这个函数将查询的文本 深度学习是一种机器学习的方法 转化为一个查询向量(tsquery);

  5. @@ 是一个运算符,用于匹配 tsvectortsquery,如果 content 字段中的文本包含 深度学习是一种机器学习的方法,则返回真(TRUE),否则返回假(FALSE)。

可以查看该查询的查询计划来验证该查询是否使用了我们创建的全文索引。

=# EXPLAIN SELECT id, title, content
FROM articles
WHERE to_tsvector('simple', content) @@ to_tsquery('simple', '机器');
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Gather Motion 4:1  (slice1; segments: 4)  (cost=13.26..52.13 rows=167 width=68)
   ->  Bitmap Heap Scan on articles  (cost=13.26..50.04 rows=42 width=68)
         Recheck Cond: (to_tsvector('simple'::regconfig, content) @@ '''机器'''::tsquery)
         ->  Bitmap Index Scan on articles_content_gin  (cost=0.00..13.25 rows=42 width=0)
               Index Cond: (to_tsvector('simple'::regconfig, content) @@ '''机器'''::tsquery)
 Optimizer: Postgres query optimizer
(6 rows)

可以看到,查询计划中出现了 Bitmap Index Scan on articles_content_gin,使用到了我们创建的 articles_content_gin 索引。

综上,这个查询利用了全文索引对 articles 表进行了全文搜索:选择出 content 字段包含 深度学习是一种机器学习的方法 的所有记录,然后返回这些记录的 idtitle,和 content 字段。