引言
目前在PostgreSQL中常见的两个中文分词插件是zhparser和pg_jieba。这里我们使用zhparser。插件的编译和安装请查看 官方文档 ,安装还是比较复杂的,建议找个现成docker镜像。
如何使用zhparser
安装相应插件
1 安装 pg_trgm
用于执行文本相似性和模糊搜索。它基于 trigram 算法,允许你在文本数据上执行模糊匹配、相似性搜索和索引。命令如下
CREATE EXTENSION pg_trgm
2 安装 zhparser
专门用于处理中文文本数据。它允许 PostgreSQL 在中文文本上执行全文搜索,包括分词、词干提取、停用词处理等操作,以便提高中文文本数据的搜索准确性和性能。命令如下
CREATE EXTENSION zhparser
创建基于zhparser的搜索配置
CREATE TEXT SEARCH CONFIGURATION chinese_zh (PARSER = zhparser)
这个命令创建了一个名为 chinese_zh
的中文文本搜索配置。该配置使用了 zhparser
解析器,表明它将用于分析和处理中文文本数据。
ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple
这个命令将指定的词汇类别(n,v,a,i,e,l)与已存在的 simple
配置进行映射。这意味着对于这些词汇类别,将使用 simple
配置的规则来进行文本分析和处理。
进行搜索查询
select ts_debug('chinese_zh', '春秋、战国是中国历史上思想迸发的时代,出现了百家争鸣的现象');
执行结果:
"(t,""time,时语素"",春秋,{},,)"
"(u,""auxiliary,助词"",、,{},,)"
"(t,""time,时语素"",战国,{},,)"
"(v,""verb,动词"",是,{simple},simple,{是})"
"(n,""noun,名词"",中国,{simple},simple,{中国})"
"(n,""noun,名词"",历史,{simple},simple,{历史})"
"(n,""noun,名词"",上思,{simple},simple,{上思})"
"(v,""verb,动词"",想,{simple},simple,{想})"
"(v,""verb,动词"",迸发,{simple},simple,{迸发})"
"(u,""auxiliary,助词"",的,{},,)"
"(n,""noun,名词"",时代,{simple},simple,{时代})"
"(u,""auxiliary,助词"",,,{},,)"
"(v,""verb,动词"",出现,{simple},simple,{出现})"
"(v,""verb,动词"",了,{simple},simple,{了})"
"(n,""noun,名词"",百家争鸣,{simple},simple,{百家争鸣})"
"(u,""auxiliary,助词"",的,{},,)"
"(n,""noun,名词"",现象,{simple},simple,{现象})"
select to_tsvector('chinese_zh', '春秋、战国是中国历史上思想迸发的时代,出现了百家争鸣的现象');
执行结果:
"'上思':4 '中国':2 '了':9 '出现':8 '历史':3 '想':5 '时代':7 '是':1 '现象':11 '百家争鸣':10 '迸发':6"
可以看到春秋和战国没有出现在里面,这里我们把t,time,时语素
的映射添加下
ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR t WITH simple;
再执行上面的语句就会得到下面的结果
"'上思':6 '中国':4 '了':11 '出现':10 '历史':5 '想':7 '战国':2 '时代':9 '春秋':1 '是':3 '现象':13 '百家争鸣':12 '迸发':8"
可以看到春秋和战国已经出现在文本向量的结果中了。我们搜索下春秋看下
select to_tsquery('战国') @@ to_tsvector('chinese_zh', '春秋、战国是中国历史上思想迸发的时代,出现了百家争鸣的现象');
true
添加自定义词典(txt)
select to_tsquery('二十四节谷') @@ to_tsvector('chinese_zh', '春秋、战国是中国历史上思想迸发的时代,在二十四节谷出现了百家争鸣的现象');
false
这里竟然没有,仔细观察上面对这个句子的向量化分析,破案了,没有把‘二十四节谷’这个词作为一个整体
'上思':6 '中国':4 '了':11 '出现':10 '历史':5 '想':7
在以下位置创建客户字典/usr/share/postgresql/14/tsearch_data/kkdict.utf8.txt
:(必须在该目录中)
#word TF IDF ATTR
二十四节谷 1 1 n
然后修改/var/lib/postgresql/data/posrgresql.conf
,在末尾添加以下行: zhparser.extra_dicts = 'kkdict.utf8.txt'
select ts_debug('chinese_zh', '春秋、战国是中国历史上思想迸发的时代,在二十四节谷出现了百家争鸣的现象');
(n,"noun,名词",二十四节谷,{simple},simple,{二十四节谷})
可见现在已经变成一个名词了。
创建索引
这里使用to_tsvector函数方式,不单独增加一列tsvector字段
create table testing(
title text
);
insert into testing values('春秋、战国是中国历史上思想迸发的时代,出现了百家争鸣的现象');
insert into testing values('春秋、战国是中国历史上思想迸发的时代,在二十四节谷出现了百家争鸣的现象');
create index ind_testing on testing using gin (to_tsvector('chinese_zh', title));
这样就可以在查询中使用中文检索了,注意当你数据量不够的时候不会走索引,会直接遍历。
select * from testing where to_tsquery('chinese_zh', '二十四节谷') @@ to_tsvector('chinese_zh', title);
总结
到这简单的使用已经介绍完毕,还能支持权重、停用词、同义词、查询结果高亮等,感兴趣的小伙伴可以看以下文档:
PostGreSQL插件
PostgreSQL官方文档了解全文检索内容
阿里云Polar DB zhparser