Manticore Search 中文分词搜索入门

news/2024/7/19 17:34:20 标签: 中文分词, 全文检索

Manticore Search 3.1.0 版引入了一种基于ICU 文本分割算法的中文文本分割新方法,该算法遵循第二种方法 - 基于字典的分割。

ICU 是一组开源库,为软件应用程序提供 Unicode 和全球化支持。与许多其他功能一起,它解决了文本边界确定的任务。 ICU 算法在文本范围内定位单词、句子、段落的位置,或者在显示文本时识别适合换行的位置。

本文截稿时,在 Manticore 的讨论区很多人反馈 ICU 似乎没有 jieba 分词器对中文分词处理的更好,Manticore作者也已经将 jieba 分词器的集成纳入后续的支持计划。

Manticore 中 ICU 分词的算法可以简单描述如下:

  • 原始文本被视为符号数组。

  • 然后 Manticore 遍历数组,如果找到一组 * 中文符号,它会将其传递给 ICU 库进行处理。

  • 中文文本的分段部分替换了原始的未分段部分。

  • 其他自然语言处理算法(charset_table、wordforms等)适用于修改后的文本,就像在常见的分割工作流程中一样。

要启用 ICU-Chinese 分词,必须在创建表时添加以下索引配置选项:

  • morphology = ‘icu_chinese’

  • charset_table = ‘chinese’ 或者 charset_table = ‘non_cjk,chinese’

当一篇文章包含中文和英文时可以考虑设置 charset_table = ‘non_cjk,chinese’

示例步骤如下

1、连接到 manticore

mysql -P 9306 -h0 

2、创建表

# 1、创建表
mysql> CREATE TABLE test_record (form_id bigint, form_data json, author string attribute indexed, content text) charset_table = 'chinese' morphology = 'icu_chinese';

# 2、查看表结构
mysql> desc test_record;
+-----------+--------+-------------------+
| Field     | Type   | Properties        |
+-----------+--------+-------------------+
| id        | bigint |                   |
| author    | string | indexed attribute |
| content   | text   | indexed stored    |
| form_id   | bigint |                   |
| form_data | json   |                   |
+-----------+--------+-------------------+

中英文混合时候参考选用 charset_table = 'non_cjk,chinese'

更多字段类型详见官方文档,地址:https://manual.manticoresearch.com/Creating_a_table/Data_types#Character-data-types

3、插入测试数据

mysql> INSERT INTO test_record (form_id, form_data, author, content) VALUES ( 226810975896997888, '{"number_1600348358244":"23347","input_1600348411983":"","input_1600348225548":"6224439990006413028","time_1600348183508":"14:36:46","input_1600348282096":"昆山市人民法院","date_1600348389097":"2022-01-14","textarea_1600348453979":"","input_1600348238915":"GADJ00020211182885","input_1600348211548":"","date_1600348174740":"2021-01-14","input_1600348428388":"","radio_1600348126943":"1","input_1600348336862":"冻结"}', '张三', '清华大学' );

mysql> INSERT INTO test_record (form_id, form_data, author, content) VALUES ( 226810975896997888, '{"date_1600345666309":"2017-08-16","input_1610335861888":"3052261","input_1600345921986":"孙善广","textarea_1600345727801":"撤销","input_1602568493757":"昆山德立亚企业管理有限公司","input_1600345853347":"1673","input_1600345648905":"274552978554269699","input_1600345839985":"3052261012019000001673","input_1600345935496":"15298824131"}', '李四', '一位牙医和一只狗在中国古代杀死一个疯子的惊人书信' );

mysql> INSERT INTO test_record (form_id, form_data, author, content) VALUES ( 226810975896997888, '{"number_1604892340550":"20","input_1604891602279":"2005","input_1604891603314":"王海燕","date_1604891845251":"2021-01-14","input_1604891608805":"蒋琮(2222)","input_1604891603984":"371311198305043420","input_1604891608483":"B1","date_1604891858785":"2021-01-14","input_1604891608176":"HR65528845","input_1604891599203":"A0020","number_1604892324841":"1"}', '李佳', '一个相扑摔跤手和一个必须在Baloon追捕法医心理学家的猎人的难以置信的插曲' );

mysql> INSERT INTO test_record (form_id, form_data, author, content) VALUES ( 269501011993878528, '{"date_1600345666309":"2019-11-14","input_1610335861888":"3052261","input_1600345921986":"郭云磊","textarea_1600345727801":"撤销","input_1602568493757":"昆山市康跃可喜安医疗器械有限公司","input_1600345853347":"2145","input_1600345648905":"274552905254612995","input_1600345839985":"3052261012017000002145","input_1600345935496":"13776098096"}', '小单', '买新的Apple电脑' );

4、分词测试

# 使用 call keywords,第一个参数为内容,第二个参数为表名
mysql> call keywords ('买新的Apple电脑', 'test_record');
+------+-----------+------------+
| qpos | tokenized | normalized |
+------+-----------+------------+
| 1    |||
| 2    | 新的      | 新的       |
| 3    | 电脑      | 电脑       |
+------+-----------+------------+
mysql> call keywords ('一位牙医和一只狗在中国古代杀死一个疯子的惊人书信', 'test_record');
+------+-----------+------------+
| qpos | tokenized | normalized |
+------+-----------+------------+
| 1    | 一位      | 一位       |
| 2    | 牙医      | 牙医       |
| 3    |||
| 4    | 一只      | 一只       |
| 5    |||
| 6    |||
| 7    | 中国      | 中国       |
| 8    | 古代      | 古代       |
| 9    | 杀死      | 杀死       |
| 10   | 一个      | 一个       |
| 11   | 疯子      | 疯子       |
| 12   |||
| 13   | 惊人      | 惊人       |
| 14   | 书信      | 书信       |
+------+-----------+------------+
mysql> call keywords ('清华大学', 'test_record');
+------+--------------+--------------+
| qpos | tokenized    | normalized   |
+------+--------------+--------------+
| 1    | 清华大学     | 清华大学     |
+------+--------------+--------------+

注:从测试 买新的Apple电脑 分词结果我们可以看到,Apple 消失了,那是因为我们设定的 charset_table 只是 chinese,如果你希望中文和英文都被分词,则你需要设置 charset_table = 'non_cjk,chinese',可以自行测试验证。

5、查询数据

5.1、普通字段查询
mysql> select id, form_id, author from test_record where form_id = 226810975896997888;
+---------------------+--------------------+--------+
| id                  | form_id            | author |
+---------------------+--------------------+--------+
| 3461355430494601233 | 226810975896997888 | 李四   |
| 3461355430494601234 | 226810975896997888 | 李佳   |
| 3461355430494601232 | 226810975896997888 | 张三   |
+---------------------+--------------------+--------+
5.2、对 string 字段进行正则查询
mysql> select id, form_id, author from test_record where form_id = 226810975896997888 and regex(author, '李.*');
+---------------------+--------------------+--------+
| id                  | form_id            | author |
+---------------------+--------------------+--------+
| 3461355430494601234 | 226810975896997888 | 李佳   |
| 3461355430494601233 | 226810975896997888 | 李四   |
+---------------------+--------------------+--------+

注:如官方文档中对 REGEX函数的描述 The REGEX(attr,expr) function returns 1 if a regular expression matches the attribute's string, and 0 otherwise. It works with both string and JSON attributes. 所示,regex 目前只能用于 string 和 json 类型的字段

5.3、对索引字段使用 match 进行搜索

只有被索引的字段才可以使用 match 进行搜索,text 类型的字段默认为 stored + indexedstring 字段默认为 attribute,但是我们可以手工为 string 字段设置 indexed 属性使之也被索引,这样 string 也可以使用 match 匹配搜索。

5.3.1、从所有索引字段搜索
# match 不指定具体字段的时,会从所有支持索引的字段中去匹配(一般包含明确指定indexed的string字段和text字段)

mysql> select id, form_id, author, content from test_record where match('牙医');
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                  |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                         |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
mysql> select id, form_id, author, content from test_record where match('李');
+---------------------+--------------------+--------+--------------------------------------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                                                |
+---------------------+--------------------+--------+--------------------------------------------------------------------------------------------------------+
| 3461355430494601234 | 226810975896997888 | 李佳   | 一个相扑摔跤手和一个必须在Baloon追捕法医心理学家的猎人的难以置信的插曲                                 |
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                                                       |
+---------------------+--------------------+--------+--------------------------------------------------------------------------------------------------------+
mysql> select id, form_id, author, content from test_record where match('小单');
+---------------------+--------------------+--------+----------------------+
| id                  | form_id            | author | content              |
+---------------------+--------------------+--------+----------------------+
| 3461355430494601235 | 269501011993878528 | 小单   | 买新的Apple电脑      |
+---------------------+--------------------+--------+----------------------+
mysql> select id, form_id, author, content from test_record where match('清华');
mysql> select id, form_id, author, content from test_record where match('清华大学');
+---------------------+--------------------+--------+--------------+
| id                  | form_id            | author | content      |
+---------------------+--------------------+--------+--------------+
| 3461355430494601232 | 226810975896997888 | 张三   | 清华大学     |
+---------------------+--------------------+--------+--------------+
5.3.2、从明确指定的索引字段搜索
# 语法:match('@field keyworld') 或者 match('@(field1,field2,...) keyworld') 

mysql> select id, form_id, author, content from test_record where match('@author 牙医');
mysql> select id, form_id, author, content from test_record where match('@(content) 牙医');
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                  |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                         |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+

# match 指定从多个字段中匹配

mysql> select id, form_id, author, content from test_record where match('@(content,author) 张三');
+---------------------+--------------------+--------+--------------+
| id                  | form_id            | author | content      |
+---------------------+--------------------+--------+--------------+
| 3461355430494601232 | 226810975896997888 | 张三   | 清华大学     |
+---------------------+--------------------+--------+--------------+
5.3.3、同时匹配多个关键字
mysql> select id, form_id, author, content from test_record where match('@(content,author) 张三|牙医');
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                  |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                         |
| 3461355430494601232 | 226810975896997888 | 张三   | 清华大学                                                                 |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
5.3.4、多个字段并且关系搜索
# 检索contnet包含“一个”并且author包含“李四”的内容
mysql> select id, form_id, author, content from test_record where match('@content 一个 @author 李四');
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                  |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                         |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+

更多关于全文索引的查询语法,详见官方文档中的 Full text operators 章节。

5.3.4、对 json 字段进行查询
# 查询json字段中某一个属性大于指定值的(数字类型比较轻注意正确选用 INTEGER、DOUBLE)
mysql> SELECT * FROM test_record WHERE INTEGER(form_data.input_1600345853347) > 1673;

# 对json中的具体字段使用精确查询
mysql> SELECT * FROM test_record WHERE form_data.input_1600345921986 = '郭云磊';

# 对json中的字段使用正则匹配查询
mysql> SELECT * FROM test_record WHERE regex(form_data.input_1600345921986, '孙.*');

官方提供了JSON字段查询的仿真教学环境,地址为 https://play.manticoresearch.com/json/,更多内容请探索官方手册。

5.4、查看查询的扩展信息

每执行一个查询后,都可以使用 SHOW META 查看执行过的查询的扩展信息,如下所示:

mysql> select id, form_id, author, content from test_record where match('@(content,author) 张三|牙医');
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| id                  | form_id            | author | content                                                                  |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
| 3461355430494601233 | 226810975896997888 | 李四   | 一位牙医和一只狗在中国古代杀死一个疯子的惊人书信                         |
| 3461355430494601232 | 226810975896997888 | 张三   | 清华大学                                                                 |
+---------------------+--------------------+--------+--------------------------------------------------------------------------+
mysql> SHOW META;
+----------------+--------+
| Variable_name  | Value  |
+----------------+--------+
| total          | 2      |
| total_found    | 2      |
| total_relation | eq     |
| time           | 0.000  |
| keyword[0]     | 张三   |
| docs[0]        | 1      |
| hits[0]        | 1      |
| keyword[1]     | 牙医   |
| docs[1]        | 1      |
| hits[1]        | 1      |
+----------------+--------+

总结

实现中文全文搜索看似通过中间件很容易,让分词结果达到自己实际业务期望度并非易事。虽然 Manticore Search 使用 ICU 已经可以轻松的应付大部分中文场景。但是当你深度使用后,可能会发现它对很多自定义词组和灵活组合变幻的中文的支持度仍然达不到我们的预期,对分词的扩展支持目前来说还不够。
不过如文初所述,作者已经计划集成 jieba 分词器(issue),相信在不久的将来支持 jieba 后我们能更灵活的自定义中文词库,来尽可能更准确的满足我们对中文分词的实际业务需求。

中文分词的官方互动教程地址:https://play.manticoresearch.com/icu-chinese/


(END)


http://www.niftyadmin.cn/n/5459701.html

相关文章

解决 linux 服务器 java 命令不生效问题

在Linux系统中,当你安装Java并设置了JAVA_HOME环境变量后,你可能需要使用source /etc/profile命令来使Java命令生效。这是因为/etc/profile是一个系统级的配置文件,它包含了系统的全局环境变量设置。 但是需要注意的是,source /e…

Python学习之-装饰器

前言: 在说装饰器之前,我们先来了解一下闭包的概念。 闭包(Closure) 定义:闭包是函数式编程的概念,在 Python 中指的是在一个外部函数中定义的内部函数,这个内部函数引用了外部函数的变量&…

[Java基础揉碎]内部类

目录 基本介绍 语法 内部内的分类 局部内部类 1.可以直接访问外部类的所有成员,包含私有的 2.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final 3.作用域:仅仅…

第三十七章 管理和监控Web网关 - Web 网关缓存表

文章目录 第三十七章 管理和监控Web网关 - Web 网关缓存表Web 网关缓存表手动关闭连接清除缓存测试服务器连接 第三十七章 管理和监控Web网关 - Web 网关缓存表 Web 网关缓存表 第四个状态表列出了 Web Gateway 响应缓存中保存的表单。 Cached Forms - 缓存表单的名称&#x…

(一)认识微服务

1. 什么是微服务 微服务是分布式架构的一种。 1.1 微服务技术 ! Spring Cloud 分布式架构就是要把服务进行拆分,拆分的过程会产生一系列问题需要解决,而Spirng Cloud 只是解决了服务拆分的过程中的服务治理问题,所以一个完整的…

如何在 Mac 上打开、编辑、复制、移动或删除存储在 Windows NTFS 格式 USB 驱动器上的文件 Tuxera NTFS for Mac使用教程

当您获得一台新 Mac 时,它只能读取 Windows NTFS 格式的 USB 驱动器。要将文件添加、保存或写入您的 Mac,您需要一个附加的 NTFS 驱动程序。Tuxera 他可以帮忙实现这一功能! Tuxera可以轻松转换驱动器:无论使用Windows PC还是Mac&…

Linux(CentOS7)安装 MongoDB

目录 下载 上传 解压 创建mongodb.conf 创建数据文件夹和日志文件夹 启动服务 创建软链接 安装客户端 下载 上传 安装 下载 官方地址: Download MongoDB Community Server | MongoDBhttps://www.mongodb.com/try/download/community 上传 将下载好的 …

解释组合模式和外观模式

组合模式(Composite Pattern)和外观模式(Facade Pattern)都是结构型设计模式,用于处理复杂系统的管理和使用,但它们解决的问题和应用场景有所不同。 组合模式: 组合模式关注于将对象组合成树状…