Elasticsearch中ik分词器的使用

栏目: 后端 · 发布时间: 6年前

内容简介:我在之前的文章中介绍过ES默认的分词器为英文分词器,对英文句子能做到比较好的分词,我们看一个例子。当输入以下请求时,对"What's your name"句子进行分词,能看到将几个词都分了出来。当输入中文"你叫什么名字"时,可以看到标准分词器将句子分成了一个一个的字,这显然在我们实际使用的过程中是没办法接受的。

1.Elasticsearch默认分词器

我在之前的文章中介绍过 Elasticsearch的安装和使用 ,这里我们使用Kibina作为 工具 来操作es,可以使用es的_analyze来分析分词器的分词结果。

ES默认的分词器为英文分词器,对英文句子能做到比较好的分词,我们看一个例子。当输入以下请求时,对"What's your name"句子进行分词,能看到将几个词都分了出来。

POST _analyze
{
  "tokenizer": "standard",
  "text": "What's your name"
}        复制代码
{
  "tokens" : [
    {
      "token" : "What's",
      "start_offset" : 0,
      "end_offset" : 6,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "your",
      "start_offset" : 7,
      "end_offset" : 11,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "name",
      "start_offset" : 12,
      "end_offset" : 16,
      "type" : "<ALPHANUM>",
      "position" : 2
    }
  ]
}复制代码

当输入中文"你叫什么名字"时,可以看到标准分词器将句子分成了一个一个的字,这显然在我们实际使用的过程中是没办法接受的。

POST _analyze
{
  "tokenizer": "standard",
  "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
    },
    {
      "token" : "么",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "名",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "字",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    }
  ]
}
复制代码

2. IK分词器

由于英文句子都是使用空{ "tokens" : [ { "token" : "你", "start_offset" : 0, "end_offset" : 1, "type" : "CN_CHAR", "position" : 0 }, { "token" : "叫什么", "start_offset" : 1, "end_offset" : 4, "type" : "CN_WORD", "position" : 1 }, { "token" : "名字", "start_offset" : 4, "end_offset" : 6, "type" : "CN_WORD", "position" : 2 } ] } 格进行分隔,因此在分词比较明确,但是中文由于语言特性,分词比较难分,也容易产生分词歧义,如果自己开发分词器,成本会比较大,所以一般在使用过程中都会用一些分词器,比较著名的有Jieba分词器,hanlp等,我们这里介绍一个es的插件分词器,ik分词器。 可以从github下载分词器的压缩包,下载地址:  github.com/medcl/elast…  ,在es的 plugins目录下创建一个ik的目录,把解压后的文件放到ik目录下,然后重启Elasticsearch。

这时,我们把之前的分词器换成ik_smart,再来看效果。可以看到用ik_smart已经能够将中文进行分词。

POST _analyze
{
  "tokenizer": "ik_smart",
  "text": "你叫什么名字"
}复制代码
{
  "tokens" : [
    {
      "token" : "你",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "叫什么",
      "start_offset" : 1,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "名字",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    }
  ]
}
复制代码

除了ik_smart之外,还有一个ik_max_wrod分词器。

  • ik_smart会将文本做比较粗粒度的切分。比如对中华人民共和国进行分词,会认为这就是一个词,结果就是一个中华人民共和国。
  • 而ik_max_word则对文本做比较细粒度的切分,会出现各种长度的词。如果同样对中华人民共和国进行分词,会分出很多的词。
{
  "tokens" : [
    {
      "token" : "中华人民共和国",
      "start_offset" : 0,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "中华人民",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "中华",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "华人",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "人民共和国",
      "start_offset" : 2,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "人民",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "共和国",
      "start_offset" : 4,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "共和",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 7
    },
    {
      "token" : "国",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "CN_CHAR",
      "position" : 8
    }
  ]
}
复制代码

这两种分词器在应对具体的场景时,需要选择合适的分词器进行使用。

3. ik_smart和ik_max_word配合使用

一般情况下,为了提高搜索的效果,需要这两种分词器配合使用。既索引时用ik_max_word尽可能多的分词,而搜索时用ik_smart尽可能提高匹配准度,让用户的搜索尽可能的准确。比如一个常见的场景,就是搜索"进口红酒"的时候,尽可能的不要出现口红相关商品或者让口红不要排在前面。

我们首先在Elasticsearch内创建一个叫goods的索引,其中名字的分词器用的是ik_max_word。

PUT /goods
{
  "mappings":{
	"goods": {
		"properties": {
			"id": {
				"type": "keyword"
			},
			"name": {
				"analyzer": "ik_max_word",
				"type": "text"
			}
		}
	  }
  },
  "settings":{
            "index": {
                "refresh_interval": "1s",
                "number_of_shards": 5,
                "max_result_window": "10000000",
                "mapper": {
                    "dynamic": "false"
                },
                "number_of_replicas": 0
            }
  }
}
复制代码

然后我们通过POST请求,往里面添加一些数据。

POST /goods/goods
{
  "id":"1",
  "name":"美丽粉色口红明星"
}

POST /goods/goods
{
  "id":"2",
  "name":"好喝的进口红酒"
}

POST /goods/goods
{
  "id":"3",
  "name":"进口红酒真好喝"
}
复制代码

最后,在查询的时候,我们指定查询分词器为ik_smart。

GET /goods/goods/_search
{
  "query":{
    "match": {
      "name": {
        "query": "进口红酒",
        "analyzer": "ik_smart"
      }
    
    }
  }
}复制代码

可以看到两条进口红酒相关的记录被搜了出来,但是口红没有被搜出来

{
  "took" : 28,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.36464313,
    "hits" : [
      {
        "_index" : "goods",
        "_type" : "goods",
        "_id" : "cdLk1WoBvRMfJWIKVfOP",
        "_score" : 0.36464313,
        "_source" : {
          "id" : "3",
          "name" : "进口红酒真好喝"
        }
      },
      {
        "_index" : "goods",
        "_type" : "goods",
        "_id" : "ctLk1WoBvRMfJWIKX_O6",
        "_score" : 0.36464313,
        "_source" : {
          "id" : "2",
          "name" : "好喝的进口红酒"
        }
      }
    ]
  }
}
复制代码

4. 总结

分词器是Elasticsearch中很重要的一部分,网上也有很多开源的分词器,对于一般的应用这些开源分词器也许足够用了,但是在某些特定的场景下,可能需要对分词器做一些优化,甚至需要自研一些分词器。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Two Scoops of Django

Two Scoops of Django

Daniel Greenfeld、Audrey M. Roy / CreateSpace Independent Publishing Platform / 2013-4-16 / USD 29.95

Two Scoops of Django: Best Practices For Django 1.5 is chock-full of material that will help you with your Django projects. We'll introduce you to various tips, tricks, patterns, code snippets, and......一起来看看 《Two Scoops of Django》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具