<
Elasticsearch自定义分词器
>
上一篇

jvisualvm监控远程服务器
下一篇

sbt打包程序
elasticsearch自定义分词器IK+Pinyin搜索

Elasticsearch默认的分词器会将中文比如”你好”拆分成”你”和”好”这两个字,然后按照倒排索引进行存储,所以默认的分词不好用,大部分时候都会自己更换分词器以达到预期的效果。推荐一个很好用的分词器,众所周知的IK分词器

简单介绍一下IK分词器中的ik_smart和ik_max_word,两者的区别就是分词粒度不一样

ik_smart:粗粒度分词
ik_max_word:细粒度分词,切分出的词尽可能的多

ik_smart粗粒度分词效果 image

ik_max_word细粒度分词效果,可以看到切分出的词非常多,ik_smart切分的词只是ik_max_word分词后的子集 image

安装IK分词器,本人使用的Elasticsearch版本是5.5.3,安装IK需要把下面命令中的5.5.3更换成自己Elasticsearch的版本号,安装完后重启Elasticsearch

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.3/elasticsearch-analysis-ik-5.5.3.zip

IK分词器详细说明参见github文档

既然中文可以搜索,那么拼音也可以进行搜索,用户时常在输入中文的时候输成了拼音,为了提高UE,也应当返回搜索结果,就像百度搜索一样 image

再介绍一下拼音分词插件,本人使用的是elasticsearch-analysis-pin插件,同IK分词插件一样,也是elastic大咖medcl的项目,详细使用详情参见github,大咖常年活跃在elastic中文社区,很多问题在中文社区都能够得到有效的解决

安装方式,同样也要更换成Elasticsearch相对应的版本号

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v5.5.3/elasticsearch-analysis-pinyin-5.5.3.zip

pinyin索引效果 image

pinyin分词器存在一个问题就是多音字不好区分,NLP语义理解一直也是比较难的部分,例如下面就没有将“银行”的拼音正确解析 image

忘记介绍了,本人使用的搜索界面是kibana,是ELK组件中的K,E是Elaisticsearch,L是Logstash,L用于日志收集,界面插件有很多,Kibana还是很好用的,强烈安利一波,Elasticsearch+Kibana环境搭建还是很简单的,在此不做过多赘述

进入正题,我们想要实现上图中百度搜索这种效果就需要把pinyin和ik进行组合搜索。先自定义分词器

PUT demo
{
  "index": {
      "analysis": {
          "filter": {
              "index_pinyin": {
                    "type": "pinyin",
                    "keep_original": true,
                    "keep_first_letter": true,
                    "keep_separate_first_letter": true,
                    "keep_full_pinyin": true,
                    "keep_joined_full_pinyin": true,
                    "keep_none_chinese_in_joined_full_pinyin": false,
                    "keep_none_chinese_in_first_letter": false,
                    "none_chinese_pinyin_tokenize": false,
                    "first_letter": "prefix",
                    "padding_char": " ",
                    "lowercase" : true,
                    "remove_duplicated_term" : true
                },
                "search_pinyin": {
                    "type": "pinyin",
                    "keep_original": true,
                    "keep_first_letter": false,
                    "keep_separate_first_letter": false,
                    "keep_full_pinyin": false,
                    "keep_joined_full_pinyin": true,
                    "keep_none_chinese_in_joined_full_pinyin": true,
                    "keep_none_chinese_in_first_letter": true,
                    "none_chinese_pinyin_tokenize": false,
                    "first_letter": "prefix",
                    "padding_char": " ",
                    "lowercase" : true,
                    "remove_duplicated_term" : true
                },
                "length":{
                  "type": "length",
                  "min":2
                }
                
            },
            "analyzer": {
                "index_ik_pinyin_analyzer": {
                    "type": "custom",
                    "tokenizer": "ik_max_word",
                    "filter": ["index_pinyin"]
                },
                "search_ik_pinyin_analyzer": {
                    "type": "custom",
                    "tokenizer": "ik_smart",
                    "filter": ["length","search_pinyin","length"]
                }
            }
            
        }
    }
}

定义了两个分词器,analyzer中的index_ik_pinyin_analyzer和search_ik_pinyin_analyzer,在filter中定义了3个过滤器,两个是pinyin类型过滤器,还有一个是length过滤器,将分词后的长度最小值设置成2,也就是去掉长度为1的词

PUT demo/items/_mapping
{
  "properties": {
    "name":{
      "type": "text",
      "analyzer": "index_ik_pinyin_analyzer",
      "search_analyzer": "search_ik_pinyin_analyzer",
      "fields": {
        "keyword":{
          "type": "keyword",
          "ignore_above": 256
        }
      }
    }
  }
}

设置mapping,type为items,只设置了一个字段name,index_ik_pinyin_analyzer用于索引,search_ik_pinyin_analyzer用于搜索,在ES中,索引做为名词就是索引的意思,做为动词可以理解成存储的意思

通过bulk API批量操作数据

POST _bulk
{"index":{"_index":"demo","_type": "items","_id": 1}}
{"name": "美国"}
{"index":{"_index":"demo","_type": "items","_id": 2}}
{"name": "英国"}
{"index":{"_index":"demo","_type": "items","_id": 3}}
{"name": "中国"}
{"index":{"_index":"demo","_type": "items","_id": 4}}
{"name": "中华人民共和国"}
{"index":{"_index":"demo","_type": "items","_id": 5}}
{"name": "gongheguo"}
{"index":{"_index":"demo","_type": "items","_id": 6}}
{"name": "刘德华"}
{"index":{"_index":"demo","_type": "items","_id": 7}}
{"name": "刘青云"}
{"index":{"_index":"demo","_type": "items","_id": 8}}
{"name": "陕西省"}
{"index":{"_index":"demo","_type": "items","_id": 9}}
{"name": "山西省"}

使用match搜索“中华人民共和国”的全拼音结果如下图 image

使用match搜索“中华人民共和国”的拼音首字母结果如下图 image

使用match搜索“中华”结果如下图 image

如果对IK分词器的效果不是很满意,可以自己整理语料,放入词库中,自定义词库路径为"config/analysis-ik/custom",同时需要修改IKAnalyzer.cfg.xml文件,在该文件中配置自定义词库的读取

推荐一个分词工具,个人认为挺好用的,是由梁斌老师提供的基于深度学习的中文在线抽词PullWord

Top
Foot