当前位置:   article > 正文

Elasticsearch:IK 中文分词器_elasticsearch ik分词器

elasticsearch ik分词器

有关 IK 分词器的作者介绍,请参阅文章 “采访IK Analyzer 中文分词器开源项目作者林良益(十三)

Elasticsearch 内置的分词器对中文不友好,只会一个字一个字的分,无法形成词语,比如:

  1. POST /_analyze
  2. {
  3. "text": "我爱北京天安门",
  4. "analyzer": "standard"
  5. }

如果我们使用的是 standard 的分词器,那么结果就是:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "我",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "<IDEOGRAPHIC>",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "爱",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "<IDEOGRAPHIC>",
  15. "position" : 1
  16. },
  17. ...
  18. {
  19. "token" : "门",
  20. "start_offset" : 6,
  21. "end_offset" : 7,
  22. "type" : "<IDEOGRAPHIC>",
  23. "position" : 6
  24. }
  25. ]
  26. }

显然这对中文来说并不友好,它显示的每一个汉字。好在 Elastic 的大拿 medcl 已经为我们做好 IK 中文分词器。下面我们来详细介绍如何安装并使用中文分词器。具体的安装步骤可以在地址 https://github.com/medcl/elasticsearch-analysis-ik 找到。

安装

首先,我们可以到如下的地址查看一下是否有最新的版本对应你的 Elasticsearch 的发行版:

https://github.com/medcl/elasticsearch-analysis-ik/releases

到目前截止日期,我们可以看到有最新的 v7.3.1 发行版。你需要根据自己的 Elasticsearch 的发行版选择同样版本的 ik 分词器进行安装。

那么,我们直接进入到我们的 Elasticsearch 的安装目录下,并打入如下的命令:

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.3.1/elasticsearch-analysis-ik-7.3.1.zip

替代上面的7.3.1安装你自己想要的版本:

安装好后,我们可以通过如下的命令来检查是否已经安装好:

  1. localhost:elasticsearch-7.3.0 liuxg$ ./bin/elasticsearch-plugin list
  2. analysis-ik

上面的命令显示我们的 IK 已经安装成功了。

这个时候需要我们重新启动一下我们的 Elasticsearch,以便这个 plugin 能装被加载。

使用 IK 分词器

根据 IK 分词器的文档,它含有如下的部分:

Analyzer:

  • ik_smart
  • ik_max_word

Tokenizer:

  • ik_smart
  • ik_max_word

我们收使用先前的句子 “我爱北京天安门” 来检查一下:

  1. POST _analyze
  2. {
  3. "text": "我爱北京天安门",
  4. "analyzer": "ik_smart"
  5. }

上面的 ik_smart 分词器显示的结果是:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "我",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "CN_CHAR",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "爱",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "CN_CHAR",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "北京",
  19. "start_offset" : 2,
  20. "end_offset" : 4,
  21. "type" : "CN_WORD",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "天安门",
  26. "start_offset" : 4,
  27. "end_offset" : 7,
  28. "type" : "CN_WORD",
  29. "position" : 3
  30. }
  31. ]
  32. }

我们接着使用 ik_max_word 分词器来试一下同样的句子:

  1. POST _analyze
  2. {
  3. "text": "我爱北京天安门",
  4. "analyzer": "ik_max_word"
  5. }

上面的 ik_max_word 分词器显示的结果为:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "我",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "CN_CHAR",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "爱",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "CN_CHAR",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "北京",
  19. "start_offset" : 2,
  20. "end_offset" : 4,
  21. "type" : "CN_WORD",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "天安门",
  26. "start_offset" : 4,
  27. "end_offset" : 7,
  28. "type" : "CN_WORD",
  29. "position" : 3
  30. },
  31. {
  32. "token" : "天安",
  33. "start_offset" : 4,
  34. "end_offset" : 6,
  35. "type" : "CN_WORD",
  36. "position" : 4
  37. },
  38. {
  39. "token" : "门",
  40. "start_offset" : 6,
  41. "end_offset" : 7,
  42. "type" : "CN_CHAR",
  43. "position" : 5
  44. }
  45. ]
  46. }

从两个输出中我们可以看出来:这两者的区别在于它们提取词项的粒度上,ik_smart 提取粒度较粗,而后者 ik_max_word 则较细,它给出更多的 token。

接下来我们创建一个索引:

PUT chinese

接下来,我们来为这个index 创建一个 mapping

  1. PUT /chinese/_mapping
  2. {
  3. "properties": {
  4. "content": {
  5. "type": "text",
  6. "analyzer": "ik_max_word",
  7. "search_analyzer": "ik_smart"
  8. }
  9. }
  10. }

运行上面的命令后,如果出现如下的信息:

  1. {
  2. "acknowledged" : true
  3. }

它表明我们的安装时成功的。

接下来,我们来导入一些文档:

  1. GET /chinese/_analyze
  2. {
  3. "text": "我爱北京天安门",
  4. "analyzer": "ik_max_word"
  5. }

显示的结果为:

  1. {
  2. "tokens" : [
  3. {
  4. "token" : "我",
  5. "start_offset" : 0,
  6. "end_offset" : 1,
  7. "type" : "CN_CHAR",
  8. "position" : 0
  9. },
  10. {
  11. "token" : "爱",
  12. "start_offset" : 1,
  13. "end_offset" : 2,
  14. "type" : "CN_CHAR",
  15. "position" : 1
  16. },
  17. {
  18. "token" : "北京",
  19. "start_offset" : 2,
  20. "end_offset" : 4,
  21. "type" : "CN_WORD",
  22. "position" : 2
  23. },
  24. {
  25. "token" : "天安门",
  26. "start_offset" : 4,
  27. "end_offset" : 7,
  28. "type" : "CN_WORD",
  29. "position" : 3
  30. },
  31. {
  32. "token" : "天安",
  33. "start_offset" : 4,
  34. "end_offset" : 6,
  35. "type" : "CN_WORD",
  36. "position" : 4
  37. },
  38. {
  39. "token" : "门",
  40. "start_offset" : 6,
  41. "end_offset" : 7,
  42. "type" : "CN_CHAR",
  43. "position" : 5
  44. }
  45. ]
  46. }

从上面的结果我们可以看出来,在我们的 token 中显示 “北京”,“天安” 及 “天安门”。这个和我们之前的是不一样的。

下面,我们输入两个文档:

  1. PUT /chinese/_doc/1
  2. {
  3. "content":"我爱北京天安门"
  4. }
  5. PUT /chinese/_doc/2
  6. {
  7. "content": "北京,你好"
  8. }

那么我们可以,通过如下的方式来进行搜索:

  1. GET /chinese/_search
  2. {
  3. "query": {
  4. "match": {
  5. "content": "北京"
  6. }
  7. }
  8. }

我们显示的结果是:

  1. {
  2. "took" : 1,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 2,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.15965709,
  16. "hits" : [
  17. {
  18. "_index" : "chinese",
  19. "_type" : "_doc",
  20. "_id" : "2",
  21. "_score" : 0.15965709,
  22. "_source" : {
  23. "content" : "北京,你好"
  24. }
  25. },
  26. {
  27. "_index" : "chinese",
  28. "_type" : "_doc",
  29. "_id" : "1",
  30. "_score" : 0.100605845,
  31. "_source" : {
  32. "content" : "我爱北京天安门"
  33. }
  34. }
  35. ]
  36. }
  37. }

因为两个文档里都含有 “北京”,我们可以看出来两个文档都被显示出来了。

我们同时做另外一个搜索:

  1. GET /chinese/_search
  2. {
  3. "query": {
  4. "match": {
  5. "content": "天安门"
  6. }
  7. }
  8. }

那么显示的结果是:

  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 1,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.73898095,
  16. "hits" : [
  17. {
  18. "_index" : "chinese",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 0.73898095,
  22. "_source" : {
  23. "content" : "我爱北京天安门"
  24. }
  25. }
  26. ]
  27. }
  28. }

因为 “天安门” 只出现在第二个文档里,所以,我们可以看出来只有一个结果。

我们也同时做另外一个搜索:

  1. GET /chinese/_search
  2. {
  3. "query": {
  4. "match": {
  5. "content": "北京天安门"
  6. }
  7. }
  8. }

在这里,我们来搜索“北京天安门”。请注意我们在 mapping 中使用了

"search_analyzer": "ik_smart"

也就是说,search_analyzer 会吧我们的“北京天安门”,分解成两个词 “北京” 及 “天安门”。这两个词将被用于搜索。通常对于 match 来说是 OR 关系,也就是说只要匹配到 “北京” 或 “天安门”,这两个之中的任何一个,那么就是匹配:

  1. {
  2. "took" : 3,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 2,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.7268042,
  16. "hits" : [
  17. {
  18. "_index" : "chinese",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 0.7268042,
  22. "_source" : {
  23. "content" : "我爱北京天安门"
  24. }
  25. },
  26. {
  27. "_index" : "chinese",
  28. "_type" : "_doc",
  29. "_id" : "2",
  30. "_score" : 0.22920427,
  31. "_source" : {
  32. "content" : "北京,你好"
  33. }
  34. }
  35. ]
  36. }
  37. }

上面显示的结果显示 “我爱北京天安门” 是最贴切的搜索结果。

如果大家想对 pinyin 分词器有兴趣的话,请参阅文章 “Elasticsearch:Pinyin analyzer”。

参考

【1】https://github.com/medcl/elasticsearch-analysis-ik

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/886125
推荐阅读
相关标签
  

闽ICP备14008679号