PostgreSQL全文检索功能FTS(Full Text Search,全文检索)
提到全文,你是否立刻想到了大名鼎鼎的Lucene
和Elasticsearch
。Elasticsearch 基于 Lucene ,并为开发者提供丰富的接口和工具,但是这也造成了它日益庞大。
使用它,你得备上大的服务器,优秀的运维团队,还要承受数据同步的心智负担。但你的需求其实很简单,只是,或者简单的全站。如果在项目的初期,花费如此大成本在上有些得不偿失。
如果本身就全文检索,那该多好啊!没错,Postgre 就全文,而且很强大,还扩展定制。
Postgre 全文是通过 FTS 配置库来的,大多数 Postgre 发行版都了 10 个以上的 FTS 配置库,我们可以通过p
的\dF
命令来查看已安装的配置库:
可以看到 Postgre 认已经安装了大量的 FTS 配置库,但是很不幸没有配置库
。但好在,Postgre 的形式来扩展 FTS,所以我们可以使用成熟的扩展库。
jieba
是国内颇为著名分词库,如果你是 Python 开发者,那么一定听过它的大名。有贡献者为 Postgre 提供了 jieba 分词——,让我们可以在 Postgre 使用到全文检索。
如果你想跟着我们一起,完成本节的实战,那么请先点开此安装 pg_jieba。
如果你安装成功,那么可以通过\dF
命令来找到jieba
相关的分词配置:
可以看到jieba
提供了4
种器,它们分别对应了不同的分词算法,如果你感兴趣,可以查阅相关的资料,这里我们不做过多的介绍,认使用jiebacfg
即可。
全文大致可分为两部分:
在 FTS 中,原始文本在构建索引之前需要被向量化。原始文本(如:字符串)必须先被向量化后才能通过 FTS 对其检索,向量化后的需要存储到单独的向量字段中,该向量的数据类型是tsvector
。
Postgre 提供了to_tsvector
来将原始文本向量化,如下:
tsvector
是由(词,序列)
组成的列表,如是原始文本中的第词,所以它的序列是
1
。
有了索引后,我们如何来索引了?
一般情况下,我们是通过关键词
来检索的,那么如何来组织关键词呢?
Postgre 提供了to_tsquery
来将词组织成tsquery
向量,然后通过向量去。tsquery
是一种特殊的数据类型,它会将关键词拼接来表示条件,如&
表示的必须包含和java
。举个复杂的例子:
在输入句子的情况下,to_tsquery
会将句子分词,然后将其拼接为tsquery
。
我们总结一下 FTS 的使用:
接下来,我们以实践的角度来使用和学习一下 FTS。
假设某个应用有点,我们将通过 FTS 来实现它。
首先,我们新建数据表:
我们需要为每篇单独新建字段fts
用来表示每篇的 tsvector 字段,并且给 fts 字段创建 gin 索引,这样后面就可以通过该字段来了。
在 语句中,我们首先为article
数据表新增了fts
字段,字段类型为tsvector
。有了该字段后,我们需要为该字段赋值,通过to_tsvector
我们将每篇的title
和content
分别向量化。
由于title
和content
的重要性不一样,的明显比数据更加重要,因此setweight
设置的权重为A
,而的权重为B
,A
的重要性大于B
。||
操作符合并向量后将结果赋给fts
。
到此,article 表中新增了 fts 字段,字段中是和词组的列表。最后为 fts 字段我们新建了索引 article_fts_gin_index 来加速我们的效率。
: || 操作符是 Postgre 的特点,表示连接、合并。
接下来,我们便可以使用全文了,条件是需包含问题
关键字,如下
Postgre 提供@@
操作符来,上面语句将问题
通过to_tsquery
转化为向量后,使用@@
来。从结果中可以看出,与问题
相关的有两篇。
注意: 在 article 表中,只有 fts 是 tsvector 字段,因此只有它能使用 @@ 操作符。
我们再尝试一下复杂的,条件是必须含有问题
和生命
两个关键字:
从结果中可以看到,全文已经可以工作了,但它还不完备,如果更新或者,发生了改变,那么索引也应该随之变化,我们可以使用触发器来这个需求点。运行如下 :