天天看点

PostgreSQL 如何高效解决 按任意字段分词检索的问题 - case 1

在有些应用场景中,可能会涉及多个字段的匹配。

例如这样的场景,一张表包含了几个字段,分别为歌手,曲目,专辑名称,作曲,歌词, 。。。

用户可能要在所有的字段中以分词的方式匹配刘德华,任意字段匹配即返回true。

传统的做法是每个字段建立分词索引,然后挨个匹配。

这样就导致sql写法很冗长,而且要使用大量的or操作。 有没有更好的方法呢?

当然有,可以将整条记录输出为一个字符串,然后对这个字符串建立分词索引。

但是问题来了,整条记录输出的格式是怎么样的,会不会影响分词结果。

record类型输出对应的源码

src/backend/utils/adt/rowtypes.c

看似不应该有问题,只是多个逗号,多了双引号,这些都是字符,scws分词应该能处理。

但是实际上有点问题,例子:

这两个词只是末尾不一样,多个个逗号就变这样了

postgresql分词的步骤简介

PostgreSQL 如何高效解决 按任意字段分词检索的问题 - case 1

.1. 使用parse将字符串拆分成多个token,以及每个token对应的token type

所以创建text search configuration时,需要指定parser,parser也是分词的核心

同时parser支持哪些token type也是建立parser时必须指定的

查看已创建了哪些parser

查看parser支持的token type如下

scws中的释义

<a href="http://www.xunsearch.com/scws/docs.php#attr">http://www.xunsearch.com/scws/docs.php#attr</a>

.2. 每种toke type,对应一个或多个字典进行匹配处理

查看已配置的token type 与 dict 的map信息

.3. 第一个适配token的字典,将token输出转换为lexeme

以下几个函数可以用来调试分词的问题

ts_token_type(parser_name text, out tokid integer, out alias text, out description text)

返回指定parser 支持的token type

ts_parse(parser_name text, txt text, out tokid integer, out token text)

指定parser, 将字符串输出为token

ts_debug(config regconfig, document text, out alias text, out description text, out token text, out dictionaries regdictionary[], out dictionary regdictionary, out lexemes text[])

指定分词配置,将字符串输出为token以及额外的信息

上面的例子,我们可以看到使用scws parser时,输出的token发生了变化

在不修改scws代码的情况下,我们可以先将逗号替换为空格,scws是会忽略空格的

<a href="https://github.com/jaiminpan/pg_jieba">https://github.com/jaiminpan/pg_jieba</a>

<a href="https://github.com/jaiminpan/pg_scws">https://github.com/jaiminpan/pg_scws</a>

<a href="https://yq.aliyun.com/articles/7730">https://yq.aliyun.com/articles/7730</a>

分词速度,每cpu核约4.44万字/s。

cpu

祝大家玩得开心,欢迎随时来 阿里云促膝长谈 业务需求 ,恭候光临。

阿里云的小伙伴们加油,努力做 最贴地气的云数据库 。