全文搜索(Full Text Search)提供了在自然语言文档(documents)中检索满足特定查询(query)条件的目标内容,并可根据相关性对结果进行排序的能力。最常见的搜索场景是查找包含指定查询词的所有文档,并按照它们与查询的相似度从高到低排列返回。
虽然传统数据库中很早就存在 LIKE、ILIKE 与正则匹配(~),但它们无法胜任现代信息检索系统:
缺乏语言学支持:无法处理词干词形派生(如搜索单数无法匹配复数形式)。
无法对检索结果的相关性进行打分排序(Ranking)。
缺乏倒排索引加速支持,每次检索必须对全表进行代价高昂的物理行全扫描。
全文索引通过对文本进行预处理建立索引:
将文档切分为记号(Tokens):由解析器(Parser)将文本拆分为单词、数字、邮箱地址等独立记号。
将记号归一化为词元(Lexemes):由词典(Dictionaries)将不同时态或复数词形归一化为词根标准形,并过滤掉无实际检索价值的停用词(Stop words)。
存储预处理后的文档结构:保存为有序词元数组,并保留词位置信息以支持词距临近打分与短语搜索。
系统为预处理文档提供了 tsvector 数据类型,为查询条件提供了 tsquery 类型(参见 Section 8.11)。核心匹配运算符是 @@。
在全文检索系统中,文档(Document)是参与搜索的基本单位。在 PostgreSQL 中,文档通常是数据表某一行中的一个文本列,或者是多个字段列的拼接组合:
SELECT title || ' ' || author || ' ' || abstract || ' ' || body AS document FROM messages WHERE mid = 12;
为了进行高效搜索,文档必须被转换为预处理后的 tsvector 格式。全部检索匹配与相关性排序完全作用于紧凑的 tsvector 结构之上,仅在最终将结果展示给前端用户时才需要读取原始文本。
全文搜索的核心逻辑建立在匹配运算符 @@ 之上。当一个 tsvector(文档)满足某个 tsquery(查询条件)时返回 true:
SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;
在 tsquery 查询表达式中,可以使用布尔操作符:
&:逻辑与(AND)
|:逻辑或(OR)
!:逻辑非(NOT)
<->:短语临近运算符(Phrase search),要求两词按指定先后间距相邻出现。
全文检索配置(Text Search Configuration)定义了解析器与词典的协同工作方式。系统根据不同的语言环境内置了多种标准配置(如 english、simple 等)。