ik分词器下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
上一篇博客讲到es的一些简单增删改查操作,当然,我们使用es肯定是为了实现一个强大的搜索功能,一般真实项目中搜索肯定是根据一个字符串去全局中搜索相关的数据,然后根据匹配到的数据分页展示到前台,es当然具备这个功能。
这里重点介绍ik的使用,es的高级查询可以去es官方文档查看,下面展示一个最基础的分页全局查询:
{
"query":{
"multi_match":{
"query":"到底是谁在碰瓷",
"fields":["EMPLOYEE_LOGINNAME", "EMPLOYEE_NAME"]
}
},
"size": 10000,
"from": 0
}
其中query为查询的字段,fields为查询的字段,size为查询的条数,from为分页开始位置,同mysql或者oracle一样。全局查询的效果已经达到了,但是有一个最严重的问题,就是es的中文分词是有问题的,比如上面的查询请求,es只能够把中文单个分开,后台检索的规则其实是包含“到”、“底”、“是”、“谁”、“在”、“碰”、“瓷”的数据,
post /{index}/_analyze
{
"analyzer":"standard",
"text":"到底是谁在碰瓷"
}
得到分词数据:
[
{
"token":"到底是",
"start_offset":0,
"end_offset":3,
"type":"CN_WORD",
"position":0
},
{
"token":"到底",
"start_offset":0,
"end_offset":2,
"type":"CN_WORD",
"position":1
},
{
"token":"是",
"start_offset":2,
"end_offset":3,
"type":"CN_CHAR",
"position":2
},
{
"token":"谁在",
"start_offset":3,
"end_offset":5,
"type":"CN_WORD",
"position":3
},
{
"token":"碰",
"start_offset":5,
"end_offset":6,
"type":"CN_CHAR",
"position":4
},
{
"token":"瓷",
"start_offset":6,
"end_offset":7,
"type":"CN_CHAR",
"position":5
}
]
这样的话肯定是不行的,很多时候不能直接搜索到我们所想要搜索的数据,到这里我们就需要整合分词插件了,分词插件能够有效的解决我们所顾虑的这个问题,我这里使用的是ik,下载地址已经贴在上面了(需要注意的是ik的版本一定要和es的版本一直)。
我们先打开es的下的plugins文件夹,新建一个名字叫ik的文件夹,然后把下载到的文件解压到ik里,重新启动es,从控制面板我们可以看到es正在自动帮我们加载ik插件
在 IKAnalyzer.cfg.xml 配置文件中配置remote_ext_dict指向远程词库地址,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://localhost/static/EsWord.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
remote_ext_dict节点为热词配置,这里写成txt格式,我们新建一个txt,在其中写入“碰瓷”两个字,然后以utf-8的格式保存,并把txt放到一个http可以访问到的地方,这里我直接放到了本地项目里,然后把访问路径写入remote_ext_dict节点下,重启es服务器,会看到
热词已经被ik检测到,同样再次重复上面检测分词效果的请求:
post /{index}/_analyze
{
"analyzer":"ik_max_word",
"text":"到底是谁在碰瓷"
}
可以看到响应结果已经变成我们想要的了
[
{
"token":"到底是",
"start_offset":0,
"end_offset":3,
"type":"CN_WORD",
"position":0
},
{
"token":"到底",
"start_offset":0,
"end_offset":2,
"type":"CN_WORD",
"position":1
},
{
"token":"是",
"start_offset":2,
"end_offset":3,
"type":"CN_CHAR",
"position":2
},
{
"token":"谁在",
"start_offset":3,
"end_offset":5,
"type":"CN_WORD",
"position":3
},
{
"token":"碰瓷",
"start_offset":5,
"end_offset":7,
"type":"CN_WORD",
"position":4
}
]
热词只要配置到txt文档中,多个以回车分隔开就可以了,启动服务后es会一直监听地址中的文件,一有变化就会重新加载热词配置,这样我们的es整合ik分词就完成了,之后的查询时热词库中的热词就不会被默认分割成单个汉字了。
最后一步,删除旧数据,重新构建索引,并在构建索引时指定分词策略
PUT /{index}
{
"settings":{
"analysis":{
"analyzer":{
"ik":{
"tokenizer":"ik_max_word"
}
}
}
}
}
构建索引需要指定分词策略,构建完索引后向新索引中插入数据,就OK啦。
ik两个分词策略的区别:
ik_max_word:会将文本做最细粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、中华人民、中华、华人、人民共和国、人民、人、民、共和国、共和、和、国国、国歌」,会穷尽各种可能的组合;
ik_smart:会将文本做最粗粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、国歌」;