Elasticsearch中,内置了很多分词器(analyzers),例如standard (标准分词器)、english (英文分词)和chinese (中文分词)。其中standard 就是无脑的一个一个词(汉字)切分,所以适用范围广,但是精准度低;english 对英文更加智能,可以识别单数负数,大小写,过滤stopwords(例如“the”这个词)等;chinese 效果很差;
1、elasticsearch官方默认的分词插件,对中文分词效果不理想。例如:
# curl 'http://172.16.32.69:9200/_analyze?pretty=true' -d '{"text":"这里是好记性不如烂笔头感叹号的博客园"}'
{
"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
}
........
]
}
总结
中文词语被分成了一个一个的汉字,这是因为使用了Elasticsearch中默认的标准分词器,这个分词器在处理中文的时候会把中文单词切分成一个一个的汉字,因此引入es之中文的分词器插件es-ik就能解决这个问题。
为何使用IK分词器?
比如“西红柿”,按默认的标准分词器搜索“西西”、“西天”等都能出现西红柿的结果,此时对于电商而言搜索效果不理想,而按IK分词器搜索“西西”、“西天”等搜索结果为空
如何集成IK分词工具
第一步:下载es的IK插件:https://github.com/medcl/elasticsearch-analysis-ik/releases(选择对应的版本,IK版本与ES版本一致,建议直接 下载编译后的zip包;若是下载源码包,则需要自己编码打包mvn clean package生成zip包)如图:
第二步:将下载的zip包(或自己编译后的包)拷贝至ES_HOME/plugins/ik(ps:ik目录没有的话自己新建一个就好),然后使用unzip命令解压
第四步:测试分词效果:
#curl 'http://172.16.32.48:9200/_analyze?analyzer=ik_max_word&pretty=true' -d '{"text":"这里是好记性不如烂笔头感叹号的博客们"}'
出现以下情况,说明IK分词器安装生效。
{
"tokens" : [
{
"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" : 1,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "好记",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "记性",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 4
}
........
]
}
IK分词器使用
首先确保IK插件安装成功(安装文档:),然后在创建mapping时,设置IK分词器,设置analyzer和search_analyzer;在java api搜索中将不用再关注IK分词器的事情,原有代码可以不做任何修改。例:
1.create a index
curl -XPUT http://localhost:9200/class
2.create a mapping
curl -XPOST http://localhost:9200/class/student/_mapping -d'
{
"student": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"age": {
"type": "long"
}
}
}
}'
3.index some docs
curl -XPOST http://localhost:9200/class/student/1 -d'
{"name":"菠菜","age":"10"}
'
curl -XPOST http://localhost:9200/class/student/2 -d'
{"name":"芹菜","age":"65"}'
curl -XPOST http://localhost:9200/class/student/3 -d'
{"name":"大萝卜 大菠菜","age":"89"}
'
4.query
curl -XPOST http://localhost:9200/class/student/_search -d'
{
"query" : { "match" : { "name" : "芹菜" } }
}
'
Result
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.25316024,
"hits": [{
"_index": "class",
"_type": "student",
"_id": "1",
"_score": 0.25316024,
"_source": {
"name": "芹菜",
"age": "10"
}
}]
}
}