最近项目上需要使用ES的同义词和自定义分词的功能,搞完了想写个总结,基本上和网上的解决方案差不多,还是抽点时间记录下(当然也还有很多别的方式实现,比如搭建一个远程服务器用来单独存储分词文件,然后通过请求服务器上的文件来实现热加载)。
1.数据库同义词表和自定义分词表;
首先需要在数据库创建两张表,假如我们就叫custom_dic(自定义分词表)和syn_dic(自定义分词表),这两张表里面都需要有一个字段存储分词,就用words这个字段存储,自定义分词存的是单个词语,同义词存的是用逗号分隔的有相同意思词语,其他字段的话可以根据自身项目需要进行增加,这里就不再细说。
2.插件开发;
(1)自定义分词需要使用ik分词器的插件(改造之后的插件下载)
首先在github上下载分词器对应插件版本的源码,我下载的是7.0.0,然后对源码进行改造,改造的方式很简单,在加载分词的地方,增加一个从数据库查询分词的方法,当然需要自己写原生的jdbc连接数据库的方式,网上搜下很多,改造完再重新打包成插件就可以了,最后直接解压放到ES的安装目录即可;后续会单独写一篇详细介绍改造ik分词器插件的内容。
(2)同义词需要使用同义词的插件(改造之后的插件下载)
同义词插件改造的方式稍微复杂点,需要调整下索引的分词结构,其他的地方也几把差不多,从数据库加载数据啥的,这里也暂时不详细介绍,后面会单独介绍,我会提供改造好的插件压缩包 ,用得着的直接用就行;
3.插件安装;
插件的安装很简单,只需要把打包好的zip解压的ES安装目录下的plugin目录下即可;
ik分词器:G:\elasticsearch-7.0.0\plugins\ik(将zip文件解压到以下ik文件夹下即可,解压之后zip文件删除);
同义词: G:\elasticsearch-7.0.0\plugins\dynamic-synonym(将zip文件解压到以下dynamic-synonym目录即可,解压之后zip文件删除)
4.配置启动;
提供的插件包中需要连接数据,参数都是通过系统环境变量的方式获取的,所以启动ES的时候需要指定相关的参数:
(1)数据库类型驱动:jdbc.driver = com.mysql.jdbc.Driver
(2)数据库地址:jdbc.url=jdbc:mysql://xxxxxx
(3)数据库用户名:jdbc.user= username
(4)数据库密码:jdbc.password=password
(5)sql语句:
加载同义词: jdbc.reload.synonym.sql=select word as words from syn_dic
加载自定义分词: jdbc.reload.sql=select word from custom_dic
以上参数直接配置到ES的启动命令里面,作为环境变量加载到ES
本人是这样启动的:
window启动:修改elasticsearch.bat文件,在%JAVA% %ES_JAVA_OPTS% 后面增加命令
linux启动: 修改elasticsearch文件,在$ES_JAVA_OPTS后面增加命令,启动的时候使用nohup命令后台启动,否则参数好像不生效
5.数据索引相关处理:
(1)新建索引时,在索引setting中增加自定义的分词器
"analysis": {
"filter": {
"synonym_custom": {
"type": "dynamic_synonym",
"synonyms_path": "fromDB",
"tokenizer": "ik_max_word"
}
},
"analyzer": {
"ik_max_word_synonym": {
"filter": "synonym_custom",
"type": "custom",
"tokenizer": "ik_max_word"
}
}
}
(2)索引中的字段分词器选择使用自定义的
"desc1": {
"type": "text",
"store": true,
"fields": {
"desc1": {
"type": "text",
"store": true,
"analyzer": "ik_max_word_synonym",
"search_analyzer": "ik_smart"
},
"untouched": {
"type": "keyword",
"store": true
}
},
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
6.针对历史数据的索引处理
重要:查询时需要指定分词器为ik_max_word_synonym,否则会查不到
(1)让自定义分词生效
调用9200端口的更新方法 updateByQuery("/"+indexName+"/_update_by_query?conflicts=proceed");
(2)让新增的同义词生效
a.如果原来的索引结构不同,那没别的办法,只能重建索引;
b.如果索引结构已经是符合条件的了,新增的分词没生效,那需要先close索引,然后再open索引
7.可能遇到的问题:
插件加载同义词或者自定义分词是通过数据库加载的,需要连接数据库,配置完启动可能会报错,还需要修改jdk运行环境的权限。
增加一行配置
permission java.net.SocketPermission "*", "connect,resolve";