1、 中文分词器

1.1 默认分词器

先来看看ElasticSearch中默认的standard 分词器,对英文比较友好,但是对于中文来说就是按照字符拆分,不是那么友好。

  1. GET /_analyze
  2. {
  3. "analyzer": "standard",
  4. "text": "中华人民共和国"
  5. }

我们想要的效果是什么:“中华人民共和国”作为一整个词语。

得到的结果是:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "中",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "<IDEOGRAPHIC>",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "华",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "<IDEOGRAPHIC>",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "人",
  19. "start_offset" : 2,
  20. "end_offset" : 3,
  21. "type" : "<IDEOGRAPHIC>",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "民",
  26. "start_offset" : 3,
  27. "end_offset" : 4,
  28. "type" : "<IDEOGRAPHIC>",
  29. "position" : 3
  30. },
  31. {
  32. "token" : "共",
  33. "start_offset" : 4,
  34. "end_offset" : 5,
  35. "type" : "<IDEOGRAPHIC>",
  36. "position" : 4
  37. },
  38. {
  39. "token" : "和",
  40. "start_offset" : 5,
  41. "end_offset" : 6,
  42. "type" : "<IDEOGRAPHIC>",
  43. "position" : 5
  44. },
  45. {
  46. "token" : "国",
  47. "start_offset" : 6,
  48. "end_offset" : 7,
  49. "type" : "<IDEOGRAPHIC>",
  50. "position" : 6
  51. }
  52. ]
  53. }

得到的结果不如人意,IK分词器就是目前最流行的es中文分词器

1.2 安装ik分词器

安装我就不详细说了,教程很多。

1.3 ik分词器基础知识

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民大会堂,人民大会,大会堂”,会穷尽各种可能的组合;

  1. GET /_analyze
  2. {
  3. "analyzer": "ik_max_word",
  4. "text": "中华人民共和国人民大会堂"
  5. }
  1. {
  2. "tokens" : [
  3. {
  4. "token" : "中华人民共和国",
  5. "start_offset" : 0,
  6. "end_offset" : 7,
  7. "type" : "CN_WORD",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "中华人民",
  12. "start_offset" : 0,
  13. "end_offset" : 4,
  14. "type" : "CN_WORD",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "中华",
  19. "start_offset" : 0,
  20. "end_offset" : 2,
  21. "type" : "CN_WORD",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "华人",
  26. "start_offset" : 1,
  27. "end_offset" : 3,
  28. "type" : "CN_WORD",
  29. "position" : 3
  30. },
  31. {
  32. "token" : "人民共和国",
  33. "start_offset" : 2,
  34. "end_offset" : 7,
  35. "type" : "CN_WORD",
  36. "position" : 4
  37. },
  38. {
  39. "token" : "人民",
  40. "start_offset" : 2,
  41. "end_offset" : 4,
  42. "type" : "CN_WORD",
  43. "position" : 5
  44. },
  45. {
  46. "token" : "共和国",
  47. "start_offset" : 4,
  48. "end_offset" : 7,
  49. "type" : "CN_WORD",
  50. "position" : 6
  51. },
  52. {
  53. "token" : "共和",
  54. "start_offset" : 4,
  55. "end_offset" : 6,
  56. "type" : "CN_WORD",
  57. "position" : 7
  58. },
  59. {
  60. "token" : "国人",
  61. "start_offset" : 6,
  62. "end_offset" : 8,
  63. "type" : "CN_WORD",
  64. "position" : 8
  65. },
  66. {
  67. "token" : "人民大会堂",
  68. "start_offset" : 7,
  69. "end_offset" : 12,
  70. "type" : "CN_WORD",
  71. "position" : 9
  72. },
  73. {
  74. "token" : "人民大会",
  75. "start_offset" : 7,
  76. "end_offset" : 11,
  77. "type" : "CN_WORD",
  78. "position" : 10
  79. },
  80. {
  81. "token" : "人民",
  82. "start_offset" : 7,
  83. "end_offset" : 9,
  84. "type" : "CN_WORD",
  85. "position" : 11
  86. },
  87. {
  88. "token" : "大会堂",
  89. "start_offset" : 9,
  90. "end_offset" : 12,
  91. "type" : "CN_WORD",
  92. "position" : 12
  93. },
  94. {
  95. "token" : "大会",
  96. "start_offset" : 9,
  97. "end_offset" : 11,
  98. "type" : "CN_WORD",
  99. "position" : 13
  100. },
  101. {
  102. "token" : "会堂",
  103. "start_offset" : 10,
  104. "end_offset" : 12,
  105. "type" : "CN_WORD",
  106. "position" : 14
  107. }
  108. ]
  109. }

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国,人民大会堂”。

  1. GET /_analyze
  2. {
  3. "analyzer": "ik_smart",
  4. "text": "中华人民共和国人民大会堂"
  5. }
  1. {
  2. "tokens" : [
  3. {
  4. "token" : "中华人民共和国",
  5. "start_offset" : 0,
  6. "end_offset" : 7,
  7. "type" : "CN_WORD",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "人民大会堂",
  12. "start_offset" : 7,
  13. "end_offset" : 12,
  14. "type" : "CN_WORD",
  15. "position" : 1
  16. }
  17. ]
  18. }

1.4 ik分词器的使用

存储时,使用ik_max_word,搜索时,使用ik_smart,原因也很容易想到:存储时,尽量存储多的可能性,搜索时做粗粒度的拆分

例如,创建以下映射

  1. PUT /my_index
  2. {
  3. "mappings": {
  4.     "properties": {
  5.       "text": {
  6.         "type": "text",
  7.         "analyzer": "ik_max_word",
  8.         "search_analyzer": "ik_smart"
  9.       }
  10.     }
  11. }
  12. }

2、ik配置文件

ik配置文件地址:插件的config目录下

部分文件内容如下:

  • IKAnalyzer.cfg.xml:用来配置自定义词库
  • main.dic:ik原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起,都会按照这个里面的词语去分词,ik原生最重要的两个配置文件之一
  • preposition.dic: 介词
  • quantifier.dic:放了一些单位相关的词,量词
  • suffix.dic:放了一些后缀
  • surname.dic:中国的姓氏
  • stopword.dic:包含了英文的停用词,a the and at but等。会在分词的时候,直接被干掉,不会建立在倒排索引中。ik原生最重要的两个配置文件之一

3、自定义词库

3.1 自定义分词词库

每年都会涌现一些特殊的流行词,内卷,耗子尾汁,不讲武德等,这些词一般不会出现在ik的原生词典里,分词的时候也不会把这些词汇当作整个词汇来进行分词。所以需要我们自己补充自己的最新的词语,到ik的词库里面。

就拿耗子尾汁来说,不做自定义分词的效果如下。

在实际的搜索过程中,肯定不希望把它分词,而是希望把它作为一个整体的词汇。

(1)首先在IK插件的config目录下,有一个IKAnalyzer.cfg.xml文件。

(2)使用Notepad++打开该文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
  3. <properties>
  4. <comment>IK Analyzer 扩展配置</comment>
  5. <!--用户可以在这里配置自己的扩展字典 -->
  6. <entry key="ext_dict"></entry>
  7. <!--用户可以在这里配置自己的扩展停止词字典-->
  8. <entry key="ext_stopwords"></entry>
  9. <!--用户可以在这里配置远程扩展字典 -->
  10. <!-- <entry key="remote_ext_dict">words_location</entry> -->
  11. <!--用户可以在这里配置远程扩展停止词字典-->
  12. <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
  13. </properties>

(3)可以看到上面的提示

(4)于是我们创建一个名为mydict.dic的文件,内容如下

(5)注意如果多个词语,就着下一行接着录入,然后把这个文件放在与配置文件的相同目录下。

(6)然后再把文件名mydict.dic添加在IKAnalyzer.cfg.xml文件中,然后保存

(7)然后重启es,查看效果

(9)可以看到,耗子尾汁这个词已经能够作为一个整体的词语来做分词了。

3.2 自定义停用词库

比如了,的,啥,么,我们可能并不想去建立索引,让人家搜索。

做法与上面自定义词库类似,这里只是简单的说一下,比方说建立一个mystop.dic文件,把不想建立的索引的词写进文件,把文件与配置文件放在同一个目录,然后在把文件名写进配置文件对应的位置,如下所示

然后在重启es,就可以查看效果了。

这样做的一个好处就是,已经有了常用的中文停用词,但是可以补充自己的停用词。

4、热更新词库

4.1 热更新

每次都是在es的扩展词典中,手动添加新词语,很坑

(1)每次添加完,都要重启es才能生效,非常麻烦

(2)es是分布式的,可能有数百个节点,你不能每次都一个一个节点上面去修改

所以引出热更新的解决方案。es不停机,直接我们在外部某个地方添加新的词语,es中立即热加载到这些新词语

热更新的方案

(1)基于ik分词器原生支持的热更新方案,部署一个web服务器,提供一个http接口,通过modified和tag两个http响应头,来提供词语的热更新,这种方式在官网也提到过。https://github.com/medcl/elasticsearch-analysis-ik


修改了插件配置之后需要重启,如果之后对远程的词库.txt文件修改就不需要再重启ES了,该插件支持热更新分词。

(2)修改ik分词器源码,然后手动支持从数据库中每隔一定时间,自动加载新的词库

一般来说采用第二种方案,第一种,ik git社区官方都不建议采用,觉得不太稳定

4.2 步骤

1、下载源码,https://github.com/medcl/elasticsearch-analysis-ik/releases

ik分词器,是个标准的java maven工程,直接导入idea就可以看到源码

2、修改源

org.wltea.analyzer.dic.Dictionary类,160行Dictionary单例类的初始化方法,在这里需要创建一个我们自定义的线程,并且启动它

org.wltea.analyzer.dic.HotDictReloadThread类:就是死循环,不断调用Dictionary.getSingleton().reLoadMainDict(),去重新加载词典

Dictionary类,399行:this.loadMySQLExtDict(); 加载mysql字典。

Dictionary类,609行:this.loadMySQLStopwordDict();加载mysql停用词

config下jdbc-reload.properties。mysql配置文件

3、mvn package打包代码

target\releases\elasticsearch-analysis-ik-7.3.0.zip

4、解压缩ik压缩包

将mysql驱动jar,放入ik的目录下

5、修改jdbc相关配置

6、重启es

观察日志,日志中就会显示我们打印的那些东西,比如加载了什么配置,加载了什么词语,什么停用词

7、在mysql中添加词库与停用词

8、分词实验,验证热更新生效

这里只是大概的一个步骤,具体情况按照自己的业务逻辑进行开发。

ElasticSearch7.3学习(十五)----中文分词器(IK Analyzer)及自定义词库的更多相关文章

  1. 【自定义IK词典】Elasticsearch之中文分词器插件es-ik的自定义词库

    Elasticsearch之中文分词器插件es-ik 针对一些特殊的词语在分词的时候也需要能够识别 有人会问,那么,例如: 如果我想根据自己的本家姓氏来查询,如zhouls,姓氏“周”.      如 ...

  2. Elasticsearch之中文分词器插件es-ik的自定义词库

    它在哪里呢? 非常重要! [hadoop@HadoopMaster custom]$ pwd/home/hadoop/app/elasticsearch-2.4.3/plugins/ik/config ...

  3. 转:solr6.0配置中文分词器IK Analyzer

    solr6.0中进行中文分词器IK Analyzer的配置和solr低版本中最大不同点在于IK Analyzer中jar包的引用.一般的IK分词jar包都是不能用的,因为IK分词中传统的jar不支持s ...

  4. 我与solr(六)--solr6.0配置中文分词器IK Analyzer

    转自:http://blog.csdn.net/linzhiqiang0316/article/details/51554217,表示感谢. 由于前面没有设置分词器,以至于查询的结果出入比较大,并且无 ...

  5. 31.IK分词器配置文件讲解以及自定义词库

    主要知识点: 知道IK默认的配置文件信息 自定义词库     一.ik配置文件     ik配置文件地址:es/plugins/ik/config目录     IKAnalyzer.cfg.xml:用 ...

  6. 30.IK分词器配置文件讲解以及自定义词库

    主要知识点: 知道IK默认的配置文件信息 自定义词库     一.ik配置文件     ik配置文件地址:es/plugins/ik/config目录     IKAnalyzer.cfg.xml:用 ...

  7. Elasticsearch之中文分词器插件es-ik的自定义热更新词库

    不多说,直接上干货! 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑         Java全栈大联盟       ...

  8. 沉淀再出发:ElasticSearch的中文分词器ik

    沉淀再出发:ElasticSearch的中文分词器ik 一.前言   为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了 ...

  9. 如何在Elasticsearch中安装中文分词器(IK)和拼音分词器?

    声明:我使用的Elasticsearch的版本是5.4.0,安装分词器前请先安装maven 一:安装maven https://github.com/apache/maven 说明: 安装maven需 ...

随机推荐

  1. MXNet源码分析 | Gluon接口分布式训练流程

    本文主要基于MXNet1.6.0版本,对Gluon接口的分布式训练过程进行简要分析. 众所周知,KVStore负责MXNet分布式训练过程中参数的同步,那么它究竟是如何应用在训练中的呢?下面我们将从G ...

  2. .NET 6学习笔记(1)——通过FileStream实现不同进程对单一文件的同时读写

    会写这篇纯属机缘巧合,虽然一直以来认为对单一文件的读.写操作是不冲突,可并行的,但实际并未实践过.正好有个UWP的程序要并行读取由Desktop Extension创建的文本,需要有个原型程序来验证, ...

  3. Eclipse插件开发demo

    一.安装 1. 下载安装JDk 2. 下载安装PDE(Plugin-in Development Environment) 访问eclipse官网,点击Download,选择Download Pack ...

  4. c++隐式类型转换存在的陷阱

    目录 目标代码 构造函数定义的隐式类型转换 分析a1 分析a2 分析a3 目标代码 旨在弄懂下面的代码,明确变量a1,a2,a3在创建时编译器究竟干了那些事: #include<iostream ...

  5. Internet/Custom路由配置——网络测试仪实操

    一.测试说明以及功能原理 本文主要介绍Internet/Custom路由配置方法以及实验: ◆作用:可以通过此功能模拟注入不同百分比掩码的路由 ◆特点:只针对路由协议(目前RIP协议不支持,因为RIP ...

  6. 打印报表工具,web报表工具对比

    ​1.jasperreport报表 有批量报表打印功能,但一般需要通过专门的编程实现批量报表打印:一些较简单的分片式打印能通过主子表实现:不能自动适应纸张大小:不支持分栏打印:不支持一纸多页打印:不支 ...

  7. c# 编程学习(三)

    方法是具名的语句序列 returnType methodName ( parameterList ) {  // 这里添加方法主体语句 } returnType(返回类型)是类型名称,指定方法返回的数 ...

  8. 【C#基础概念】程序集Assembliy

    一.      程序集定义 二.      程序集结构 通常,静态程序集可能由以下四个元素组成: 程序集清单(manifest) 类型元数据metadata和程序集元数据. 实现这些类型的 Micro ...

  9. System.Console.WriteLine() 调用原理

    1.System.Console.WriteLine(类的实例)默认调用类的Tostring()方法.如果自定义的新类未override ToString()方法.那么调用Object.ToStrin ...

  10. Objective-C 基础教程第五章,复合

    目录 Objective-C 基础教程第五章,复合 什么是复合? Car程序 自定义NSLog() 存取方法get Set Tires(轮胎) 存取方法 Car类代码的其他变化 扩展Car程序 复合还 ...