# 分词
ik-analyzer、结巴中文分词、THULAC、NLPIR和阿里的aliws
# version
| IK version | ES version |
|---|---|
| master | 7.x -> master |
| 6.x | 6.x |
| 5.x | 5.x |
| 1.10.6 | 2.4.6 |
| 1.9.5 | 2.3.5 |
| 1.8.1 | 2.2.1 |
| 1.7.0 | 2.1.1 |
| 1.5.0 | 2.0.0 |
| 1.2.6 | 1.0.0 |
| 1.2.5 | 0.90.x |
| 1.1.3 | 0.20.x |
| 1.0.0 | 0.16.2 -> 0.19.0 |
# 安装
C:\Green\elasticsearch-6.4.3\bin> .\elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/r
eleases/download/v6.4.3/elasticsearch-analysis-ik-6.4.3.zip
1
2
2
TIP
版本对应,不要弄错
启动日志将会有以下信息
[2020-12-25T14:19:03,332][INFO ][o.e.p.PluginsService ] [cFIDIIy] loaded plugin [analysis-ik]
1
# 基础知识
IK分词器包含两种analyzer,一般用ik_max_word
- ik_max_word:会将文本做最细粒度的拆分
- ik_smart:会做最粗粒度的拆分
# 配置文件
ik插件安装完成后,可以在elasticsearch-6.4.3/config/analysis-ik看到ik的配置文件IKAnalyzer.cfg.xml
该目录下带有许多文件,含义如下:
main.dic ik 原生内置的中文词库,里面有275909条现成的词语quantifier.dic量词和单位名称,如个,斤,克,米之类的suffix.dic常见后缀词,如江,村,省,市,局等surname.dic中国姓氏stopword.dic停用词,目前默认的是写的几个英文单词,如and, a, the等preposition.dic副词、语气助词,连接词等无实际含义的词语,如却,也,是,否则之类的
还提供了额外的词库补充文件,extra开头的那几个就是,如extra_main.dic,共收录398716条现有的词语,默认没有使用,有需要可以在配置文件IKAnalyzer.cfg.xml上添加
最重要的字典
最重要的是main.dic和stopword.dic。stopword(停用词),分词时会直接被干掉,不会建立在倒排索引中。
# 自定义词库
- 创建自定义词库文件
mydic.dic,并在IKAnalyzer.cfg.xml的ext_dict属性里加上该文件名,可以在mydic.dic文件里补充自己的词汇,如网络流行词:跪族篮孩。
添加前的分词效果:
GET /forum/_analyze
{
"text": "跪族篮孩",
"analyzer": "ik_max_word"
}
响应结果:
{
"tokens": [
{
"token": "跪",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 0
},
{
"token": "族",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": "篮",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 2
},
{
"token": "孩",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 3
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
添加词库后:
{
"tokens": [
{
"token": "跪族篮孩", //能看到完整的“跪族篮孩”,能看到完整的语词出现。
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 0
},
{
"token": "跪",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 1
},
{
"token": "族",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 2
},
{
"token": "篮",
"start_offset": 2,
"end_offset": 3,
"type": "CN_WORD",
"position": 3
},
{
"token": "孩",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 4
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
- 自己建立停用词库,如了,的,哈,啥,这几个字不想去建立索引 在配置文件IKAnalyzer.cfg.xml下ext_stopwords标签添加:extra_stopword.dic,并加几个词,修改后同样要重启es。
加一个"啥"字在ext_stopword中 修改前:
GET /forum/_analyze
{
"text": "啥都好",
"analyzer": "ik_max_word"
}
响应结果:
{
"tokens": [
{
"token": "啥",
"start_offset": 0,
"end_offset": 1,
"type": "CN_WORD",
"position": 0
},
{
"token": "都好",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
添加停用词后
{
// 那个啥字直接没有了,结果符合预期。
"tokens": [
{
"token": "都好",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 0
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 热更新方案
上面自定义词库有一个致命问题:必须要重启ES,新增的词库才能生效。
基于id分词器原生支持的更新方案,部署一个web服务器,提供一个http接口,通过modified和try两个http响应头,来提供词语的热更新操作。- 修改ik分词器源码,然后手动支持从mysql中每隔一定时间,自动加载新的词库。
推荐方案2
- 下载源码
- 修改
org.wltea.analyzer.dic.Dictionary- 主要思路是在这个类的
initial()方法内增加一个入口,反复去调用reLoadMainDict()方法,此方法如下:
- 主要思路是在这个类的
public void reLoadMainDict() {
logger.info("重新加载词典...");
// 新开一个实例加载词典,减少加载过程对当前词典使用的影响
Dictionary tmpDict = new Dictionary(configuration);
tmpDict.configuration = getSingleton().configuration;
tmpDict.loadMainDict();
tmpDict.loadStopWordDict();
_MainDict = tmpDict._MainDict;
_StopWords = tmpDict._StopWords;
logger.info("重新加载词典完毕...");
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11