一、前言

ik分词器是一个方便中文分词的工具,在英文中,基本是一个个的单词表征含义,而中文的词语分割很重要,比如小米手机,如果不用IK分词器,ES默认的分词结果是“小”“米”“手”“机”,而安装了分词器之后,可以识别“小米”“手机”。在大数据量的情况下,可以更优先地匹配词组,而不是将每个字单独匹配

除基本单词切割外,我们也可以自己定义需要的单词,例如如果有必要的话,可以在配置文件中加入“米手”,单词分割就可以识别“小米”“米手”“手机”。利用分词器可以增强检索效果,更好地匹配数据内容,符合中文习惯。在ES中,检索到的数据会得到一个得分,越高的匹配度可以得到更高的得分。之前对停用词不是特别明白,去查了查相关资料。

停用词:指文本中出现频率很高,但实际意义又不大的词,主要指副词、虚词、语气词等。如“是”、“而是”等。 它主要用在信息检索中。在为文本或网页建立索引的时候,会去掉这些词。

举个例子,在百度搜索:你是小明吗 如果有完全符合的,会显示在最上面,你可以观察后几页模糊搜索的数据,有关键字是“你”的、“你是”的、“小明”的,但是没有关键字是“吗”的,这个“吗”就被百度的停用词库给过滤掉了,因为它跟你要查询的信息“你和小明的关系”没有实际的关联。

二、安装

1.版本

我们要先找到对应我们ES版本的IK分词器,在github上查看对应:https://github.com/medcl/elasticsearch-analysis-ik/blob/master/README.md

2.下载IK压缩包

找到对应后在该网页下载:https://github.com/medcl/elasticsearch-analysis-ik/releases

这里要注意一点,网站提供了两种zip压缩包,建议是安装第一个完整版,如果安装的是第二个zip,可能会报错,详情见问题小结1.

3.创建ik文件夹

在elasticsearch/plugins路径下创建ik文件夹,将压缩包放置在该文件夹下并解压,以我的例子,要运行的代码是:

cd /data/elk-ayers/elasticsearch-7.10.1-node01/plugins/

mkdir ik
cd ik

unzip elasticsearch-analysis-ik-7.10.1.zip

即将压缩包解压在ik文件夹下

4.重启ES(ES5.0以上版本直接执行(2))

(1)配置elasticsearch.yml(ES5.0以上版本请忽略

在elasticsearch.yml配置文件中加入一句index.analysis.analyzer.ik.type : “ik”,否则有可能报错,详情见问题小结2

vim /data/elk-ayers/elasticsearch-7.10.1-node01/config/elasticsearch.yml
index.analysis.analyzer.ik.type : "ik"

(2)重启ES,可以看到相关文件加载了。这里注意:如果是个ES集群,那么在每个节点上都要安装IK分词器。否则可能在创建索引时会遇到问题小结4的报错。

三、自定义词语配置

1.创建custom文件夹

在plugins/ik/config/目录下创建一个custom文件夹

cd /data/elk-ayers/elasticsearch-7.10.1-node01/plugins/ik/config
mkdir custom

2.创建my_word.dic文件

在custom文件夹下创建一个my_word.dic文件,直接在其中加入我们想要识别的词组

cd custom
vim my_word.dic

3.配置IKAnalyser.cfg.xml文件

在plugins/ik/config/目录下编辑IKAnalyser.cfg.xml,修改对应内容

vim /data/elk-ayers/elasticsearch-7.10.1-node01/plugins/ik/config/IKAnalyzer.cfg.xml

 

三、使用测试

以下是几个测试,在Kibana的Dev tools 输入,执行语句段,索引结果将按照匹配得分的高低降序输出。观察输出结果就能更好地理解IK分词器的作用,有好的样例我也会继续更新。

样例1:

下载完IK分词器后,我们的ES中存在三种模式的分词:Ik(ik_smart 、 ik_max_word)、standard(es自带的)。如果我们不指定分词模式,则默认会执行standard,语句被拆分成一个一个字。而ik_max_word是最细粒度的拆分,也是ik默认的,ik_smart是做最粗粒度的拆分。

举个最简单的例子,对于“进口红酒”,三种拆分分别是:

standard:进、口、红、酒

ik_smart:进口、红酒

ik_max_word:进口、口红、红酒

POST _analyze
{
    "text": "进口红酒"
}

POST _analyze
{
    "analyzer": "ik_smart",
    "text": "进口红酒"
}

POST _analyze
{
    "analyzer": "ik_max_word",
    "text": "进口红酒"
}

样例2:

1.PUT创建索引模式,以ik_max_word为分词器

PUT ik_index
{
    "mappings": {
        "properties": {
            "id": {
                "type": "long"
            },
            "title": {
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
    }
}

2.GET查看所创建的索引映射,POST在索引中插入数据,id分别为1234

GET ik_index/_mapping

POST ik_index/_doc/1
{
    "content": "美国留给伊拉克的是个烂摊子吗"
}

POST ik_index/_doc/2
{
  "content": "公安部:各地校车将享最高路权"
}

POST ik_index/_doc/3
{
  "content": "中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"
}

POST ik_index/_doc/4
{
  "content": "中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
}

3.POST 进行查询操作,会发现对“中国”的匹配结果反而比“中”多,这是因为ik_max_word进行最细粒度拆分,如果检索“中国”,会出现对“中”“国”“中国”的检索结果,所以往往包含更多内容

POST ik_index/_search
{
  "query": { "match": { "content": "中" } }
}

POST ik_index/_search
{
  "query": { "match": { "content": "中国" } }
}

样例3:

1.PUT创建索引模式,添加两个fields,分别是“title.cn”(中文检索方式采用ik_smart)和“title.en”(英文检索方式采用普通english),如果字段选择“title”,则为ES默认检索standard方式。

PUT ik2_index
{
    "mappings": {
        "properties": {
            "id": {
                "type": "long"
            },
            "title": {
                "type": "text",
                "fields": {
                   "cn": {
                       "type": "text",
                       "analyzer": "ik_smart"
                   },
                   "en": {
                       "type": "text",
                       "analyzer": "english"
                   }
                }
            }
        }
    }
}

2.批量插入数据

POST _bulk
{ "index" : { "_index" : "ik2_index", "_id" : "1" } }
{ "title" : "周星驰最新电影" }
{ "index" : { "_index" : "ik2_index", "_id" : "2" } }
{ "title" : "周星驰最好看的新电影" }
{ "index" : { "_index" : "ik2_index", "_id" : "3" } }
{ "title" : "周星驰最新电影,最好,新电影" }
{ "index" : { "_index" : "ik2_index", "_id" : "4" } }
{ "title" : "最最最最好的新新新新电影" }
{ "index" : { "_index" : "ik2_index", "_id" : "5" } }
{ "title" : "I'm not happy about the foxes" }
{ "index" : { "_index" : "ik2_index", "_id" : "6" } }
{ "title" : "LOL是好玩的游戏" }

3.检索数据,POST和GET操作都可以使用,效果相同但格式略有不同。

不过前两段是无法匹配到结果的,因为默认的standard模式对英文以单词分词,只能匹配到foxes,而无法匹配fox,所以可以采用title+foxes或者title.en+fox来正确检索

POST ik2_index/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "fox",
      "fields": "title"
    }
  }
}

GET ik2_index/_search
{
  "query": {
    "match": {
        "title": "fox"
    }
  }
}

GET ik2_index/_search
{
  "query": {
    "match": {
        "title": "foxes"
    }
  }
}

GET ik2_index/_search
{
  "query": {
    "match": {
        "title.en": "fox"
    }
  }
}

4.不同检索方式,title.cn(ik_smart)、title.en(english)、title(standard)对比

对于这一部分代码,第二段匹配到的比第一段内容要多,因为我们采用的title.cn是ik_smart,则词语只能被拆分成字符串中没有重复字符的字段。例如只能拆分成类似the+最好+游戏,而不能the+最+最好+游戏

GET ik2_index/_search
{
  "query": {
    "match": {
        "title.cn": "the最好游戏"
    }
  }
}

GET ik2_index/_search
{
  "query": {
    "match": {
        "title.en": "the最好游戏"
    }
  }
}

 对于这一段代码,大家可以自己观察输出结果总结差异

POST ik2_index/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "the最新游戏",
      "fields": "title.cn"
    }
  }
}

POST ik2_index/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "the最新游戏",
      "fields": "title.en"
    }
  }
}

POST ik2_index/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "the最新游戏",
      "fields": "title"
    }
  }
}

POST ik2_index/_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "the最新游戏",
      "fields": [ "title.cn", "title.cn", "title.en"]
    }
  }
}

 

参考博客:

Elasticsearch之插件Ik分词器详细测试

ES7学习笔记(七)IK中文分词器

elasticsearch ik中文分词器的使用详解【这个链接中的代码需要自己进行相应微调,创建和查询:参考第一个链接调整;_bulk批量插入:根据Elasticsearch 7 : 通过 _bulk 批量添加文档修改定义】

问题小结(单击链接跳转解决方案):

1.could not load plugin descriptor for plugin directory []/Likely root cause......plugins/ik/plugin-descriptor.properties

2.custom analyzer [ik] failed to find tokenizer under name []

主要是在elasticsearch.yml中的配置问题,由于我已经是ES7.10.1版本,不需要进行配置,因此没有测试,只给出了几个参考博客

Elasticsearch如何安装中文分词插件ik

Elasticsearch 默认配置 IK 及 Java AnalyzeRequestBuilder 使用

3.node settings must not contain any index level settings

4.analyzer [] has not been configured in mappings []

报这个错误的原因主要是没有安装分词器。如果自己搭建的是一个ES集群,那么需要在每个节点进行IK分词器的安装,而不是仅仅安装在主节点

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐