发布时间:2021-04-22 13:15:31编辑:admin阅读(3455)
elasticsearch官方默认的分词插件,对中文分词效果不理想。
中文的分词器现在大家比较推荐的就是 IK分词器,当然也有些其它的比如 smartCN、HanLP。
这里只讲如何使用IK做为中文分词。
操作系统:centos 7.6
docker版本:19.03.12
ip地址:192.168.31.165
这里安装7.10.1版本
docker pull elasticsearch:7.5.1
vi /etc/sysctl.conf
调整参数
vm.max_map_count=262144
刷新参数
sysctl -p
注意,系统参数一定要修改,否则参数过低,会造成elasticsearch启动失败。
mkdir -p /data/elk7/elasticsearch/{data,logs,config,plugins} vi /data/elk7/elasticsearch/config/elasticsearch.yml
内容如下:
cluster.name: "docker-cluster" network.host: 0.0.0.0
以单例模式启动
docker run -d --name=elasticsearch \ -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" elasticsearch:7.10.1
等待30秒左右,查看docker日志,是否有错误日志
访问elasticsearch页面
http://192.168.31.165:9200/
效果如下:
拷贝数据到持久化目录,并重新启动elasticsearch
docker cp elasticsearch:/usr/share/elasticsearch/data /data/elk7/elasticsearch/ docker cp elasticsearch:/usr/share/elasticsearch/logs /data/elk7/elasticsearch/ chmod 777 -R /data/elk7/elasticsearch/ docker rm -f elasticsearch docker run -d --name=elasticsearch \ --restart=always \ -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ -v /data/elk7/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /data/elk7/elasticsearch/data:/usr/share/elasticsearch/data \ -v /data/elk7/elasticsearch/logs:/usr/share/elasticsearch/logs \ elasticsearch:7.10.1
再次刷新页面,效果同上。
打开github地址:https://github.com/medcl/elasticsearch-analysis-ik
打开releases页面,下载7.10.1版本
注意:这个版本,必须和elasticsearch对应。
下载完成后,将文件elasticsearch-analysis-ik-7.10.1.zip上传到/opt目录
解压到指定目录
mkdir /data/elk7/elasticsearch/plugins/elasticsearch-analysis-ik unzip /opt/elasticsearch-analysis-ik-7.10.1.zip -d /data/elk7/elasticsearch/plugins/elasticsearch-analysis-ik
设置文件权限
chmod 777 -R /data/elk7/elasticsearch/
重新启动elasticsearch
docker rm -f elasticsearch docker run -d --name=elasticsearch \ --restart=always \ -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ -v /data/elk7/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /data/elk7/elasticsearch/data:/usr/share/elasticsearch/data \ -v /data/elk7/elasticsearch/logs:/usr/share/elasticsearch/logs \ -v /data/elk7/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ elasticsearch:7.10.1
注意:这里是新挂载了plugins目录,用来存放插件的。
查看插件接口
http://192.168.31.165:9200/_cat/plugins
输出:
e30bb0e85e63 analysis-ik 7.10.1
说明插件安装成功了。
请求url:
http://192.168.31.165:9200/_analyze
首先我们通过Postman发送GET请求查询分词效果
先指定Headers,Content-Type=application/json
再指定请求参数
{ "text":"农业银行" }
效果如下:
得到如下结果,可以发现es的默认分词器无法识别中文中农业
、银行
这样的词汇,而是简单的将每个字拆完分为一个词,这显然不符合我们的使用要求。
{ "tokens": [ { "token": "农", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "业", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "银", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 }, { "token": "行", "start_offset": 3, "end_offset": 4, "type": "<IDEOGRAPHIC>", "position": 3 } ] }
上面已经安装ik中文分词器,接下来使用它。
我们这次加入新的参数"analyzer":"ik_max_word"
k_max_word:会将文本做最细粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、中华人民、中华、华人、人民共和国、人民、人、民、共和国、共和、和、国国、国歌」,会穷尽各种可能的组合
ik_smart:会将文本做最粗粒度的拆分,例如「中华人民共和国国歌」会被拆分为「中华人民共和国、国歌」
修改postman请求参数为:
{ "analyzer":"ik_max_word", "text":"农业银行" }
得到如下结果
{ "tokens": [ { "token": "农业银行", "start_offset": 0, "end_offset": 4, "type": "CN_WORD", "position": 0 }, { "token": "农业", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 1 }, { "token": "银行", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 2 } ] }
百度搜索中每天都会收录新的词汇,es中也可以进行扩展词汇。
我们首先查询弗雷尔卓德字段
修改postman请求参数为:
{ "analyzer":"ik_max_word", "text":"弗雷尔卓德" }
仅仅可以得到每个字的分词结果,我们需要做的就是使分词器识别到弗雷尔卓德
也是一个词语。
{ "tokens": [ { "token": "弗", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR", "position": 0 }, { "token": "雷", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR", "position": 1 }, { "token": "尔", "start_offset": 2, "end_offset": 3, "type": "CN_CHAR", "position": 2 }, { "token": "卓", "start_offset": 3, "end_offset": 4, "type": "CN_CHAR", "position": 3 }, { "token": "德", "start_offset": 4, "end_offset": 5, "type": "CN_CHAR", "position": 4 } ] }
首先进入es根目录中的plugins文件夹下的ik文件夹,进入config目录,创建custom.dic
文件
cd /data/elk7/elasticsearch/plugins/elasticsearch-analysis-ik/config vi custom.dic
写入以下内容
弗雷尔卓德 弗雷尔 卓 德
打开IKAnalyzer.cfg.xml文件,将新建的custom.dic
配置其中
<?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">custom.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords"></entry> <!--用户可以在这里配置远程扩展字典 --> <!-- <entry key="remote_ext_dict">words_location</entry> --> <!--用户可以在这里配置远程扩展停止词字典--> <!-- <entry key="remote_ext_stopwords">words_location</entry> --> </properties>
注意:仅仅修改<entry key="ext_dict"></entry> 这一行内容即可
重启es
docker restart elasticsearch
再次查询发现es的分词器可以识别到弗雷尔卓德词汇
{ "tokens": [ { "token": "弗雷尔卓德", "start_offset": 0, "end_offset": 5, "type": "CN_WORD", "position": 0 }, { "token": "弗雷尔", "start_offset": 0, "end_offset": 3, "type": "CN_WORD", "position": 1 }, { "token": "卓", "start_offset": 3, "end_offset": 4, "type": "CN_WORD", "position": 2 }, { "token": "德", "start_offset": 4, "end_offset": 5, "type": "CN_WORD", "position": 3 } ] }
1. 创建索引
进入linux系统,手动执行。
curl -XPUT http://localhost:9200/index
2.创建一个映射
curl -XPOST http://localhost:9200/index/_mapping -H 'Content-Type:application/json' -d' { "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } }'
3. 索引加入一些文档
curl -XPOST http://localhost:9200/index/_create/1 -H 'Content-Type:application/json' -d' {"content":"美国留给伊拉克的是个烂摊子吗"} ' curl -XPOST http://localhost:9200/index/_create/2 -H 'Content-Type:application/json' -d' {"content":"公安部:各地校车将享最高路权"} ' curl -XPOST http://localhost:9200/index/_create/3 -H 'Content-Type:application/json' -d' {"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"} ' curl -XPOST http://localhost:9200/index/_create/4 -H 'Content-Type:application/json' -d' {"content":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"} '
4. 带高亮显示的查询
curl -XPOST http://localhost:9200/index/_search -H 'Content-Type:application/json' -d' { "query" : { "match" : { "content" : "中国" }}, "highlight" : { "pre_tags" : ["<tag1>", "<tag2>"], "post_tags" : ["</tag1>", "</tag2>"], "fields" : { "content" : {} } } } '
注意:
highlight表示高亮显示。
pre_tags,post_tags表示,匹配关键字后,增加标记。
fields 表示
输出:
{ "took": 174, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 3, "relation": "eq" }, "max_score": 1.2257079, "hits": [ { "_index": "index", "_type": "_doc", "_id": "3", "_score": 1.2257079, "_source": { "content": "中韩渔警冲突调查:韩警平均每天扣1艘中国渔船" }, "highlight": { "content": [ "<tag1>中</tag1>韩渔警冲突调查:韩警平均每天扣1艘<tag1>中</tag1><tag1>国</tag1>渔船" ] } }, { "_index": "index", "_type": "_doc", "_id": "4", "_score": 0.9640833, "_source": { "content": "中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首" }, "highlight": { "content": [ "<tag1>中</tag1><tag1>国</tag1>驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首" ] } }, { "_index": "index", "_type": "_doc", "_id": "1", "_score": 0.3864615, "_source": { "content": "美国留给伊拉克的是个烂摊子吗" }, "highlight": { "content": [ "美<tag1>国</tag1>留给伊拉克的是个烂摊子吗" ] } } ] } }
上午已经提到了如何自定义字典文件,比如:custom.dic。这里不做重复介绍,请查看上文操作。
目前该插件支持热更新 IK 分词,通过上文在 IK 配置文件中提到的如下配置
<!--用户可以在这里配置远程扩展字典 --> <entry key="remote_ext_dict">location</entry> <!--用户可以在这里配置远程扩展停止词字典--> <entry key="remote_ext_stopwords">location</entry>
其中 location
是指一个 url,比如 http://yoursite.com/getCustomDict
,该请求只需满足以下两点即可完成分词热更新。
该 http 请求需要返回两个头部(header),一个是 Last-Modified
,一个是 ETag
,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
该 http 请求返回的内容格式是一行一个分词,换行符用 \n
即可。
满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。
可以将需自动更新的热词放在一个 UTF-8 编码的 .txt 文件里,放在 nginx 或其他简易 http server 下,当 .txt 文件修改时,http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。可以另外做一个工具来从业务系统提取相关词汇,并更新这个 .txt 文件。
注意:远程扩展字典,需要自己写api,根据实际业务情况而定。我目前还未找到公开的远程扩展字典api,支持任何用户访问的那种。
本文参考链接:
https://github.com/medcl/elasticsearch-analysis-ik
https://www.cnblogs.com/haixiang/p/11810799.html
47604
45984
36909
34467
29079
25713
24565
19714
19245
17756
5564°
6155°
5690°
5737°
6704°
5482°
5484°
5988°
5965°
7295°