爲Elasticsearch添加中文分詞,對比分詞器效果

lasticsearch中,內置了不少分詞器(analyzers),例如standard (標準分詞器)、english(英文分詞)和chinese (中文分詞)。其中standard 就是無腦的一個一個詞(漢字)切分,因此適用範圍廣,可是精準度低;english 對英文更加智能,能夠識別單數負數,大小寫,過濾stopwords(例如「the」這個詞)等;chinese 效果不好,後面會演示。此次主要玩這幾個內容:安裝中文分詞ik,對比不一樣分詞器的效果,得出一個較佳的配置。關於Elasticsearch,以前還寫過兩篇文章:Elasticsearch的安裝,運行和基本配置 和 備份和恢復,須要的能夠看下。html

 

安裝中文分詞ik

Elasticsearch的中文分詞很爛,因此咱們須要安裝ik。首先從github上下載項目,解壓:git

 

  1. cd /tmp
  2. wget https://github.com/medcl/elasticsearch-analysis-ik/archive/master.zip
  3. unzip master.zip
  4. cd elasticsearch-analysis-ik/

 

而後使用mvn package 命令,編譯出jar包 elasticsearch-analysis-ik-1.4.0.jar。github

 

  1. mvn package

 

將jar包複製到Elasticsearch的plugins/analysis-ik 目錄下,再把解壓出的ik目錄(配置和詞典等),複製到Elasticsearch的config 目錄下。而後編輯配置文件elasticsearch.yml ,在後面加一行:chrome

 

  1. index.analysis.analyzer.ik.type : "ik"

 

重啓service elasticsearch restart 。搞定。api

若是上面的mvn搞不定的話,你能夠直接從 elasticsearch-rtf 項目中找到編譯好的jar包和配置文件(我就是怎麼幹的)。app

2014-12-14晚更新,今天是星期天,我在vps上安裝ik分詞,一樣的步驟,老是提示MapperParsingException[Analyzer [ik] not found for field [cn]],而後晚上跑到公司,發現我公司虛擬機上Elasticsearch的版本是1.3.2,vps上是1.3.4,猜是版本問題,直接把vps從新安裝成最新的1.4.1,再安裝ik,竟然ok了……】elasticsearch

 

準備工做:建立索引,錄入測試數據

先爲後面的分詞器效果對比作好準備,個人Elasticsearch部署在虛擬機 192.168.159.159:9200 上的,使用chrome的postman插件直接發http請求。第一步,建立index1 索引:post

 

  1. PUT http://192.168.159.159:9200/index1
  2. {
  3. "settings": {
  4. "refresh_interval": "5s",
  5. "number_of_shards" : 1, // 一個主節點
  6. "number_of_replicas" : 0 // 0個副本,後面能夠加
  7. },
  8. "mappings": {
  9. "_default_":{
  10. "_all": { "enabled": false } // 關閉_all字段,由於咱們只搜索title字段
  11. },
  12. "resource": {
  13. "dynamic": false, // 關閉「動態修改索引」
  14. "properties": {
  15. "title": {
  16. "type": "string",
  17. "index": "analyzed",
  18. "fields": {
  19. "cn": {
  20. "type": "string",
  21. "analyzer": "ik"
  22. },
  23. "en": {
  24. "type": "string",
  25. "analyzer": "english"
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }
  32. }

 

爲了方便,這裏的index1 索引,只有一個shards,沒有副本。索引裏只有一個叫resource 的type,只有一個字段title ,這就足夠咱們用了。title 自己使用標準分詞器,title.cn 使用ik分詞器,title.en 自帶的英文分詞器。而後是用bulk api批量添加數據進去:測試

 

  1. POST http://192.168.159.159:9200/_bulk
  2. { "create": { "_index": "index1", "_type": "resource", "_id": 1 } }
  3. { "title": "周星馳最新電影" }
  4. { "create": { "_index": "index1", "_type": "resource", "_id": 2 } }
  5. { "title": "周星馳最好看的新電影" }
  6. { "create": { "_index": "index1", "_type": "resource", "_id": 3 } }
  7. { "title": "周星馳最新電影,最好,新電影" }
  8. { "create": { "_index": "index1", "_type": "resource", "_id": 4 } }
  9. { "title": "最最最最好的新新新新電影" }
  10. { "create": { "_index": "index1", "_type": "resource", "_id": 5 } }
  11. { "title": "I'm not happy about the foxes" }

 

注意bulk api要「回車」換行,否則會報錯。spa

 

各類比較

一、對比ik分詞,chinese分詞和standard分詞

 

  1. POST http://192.168.159.159:9200/index1/_analyze?analyzer=ik
  2. 聯想召回筆記本電源線

 

ik測試結果:

 

  1. {
  2. "tokens": [
  3. {
  4. "token": "聯想",
  5. "start_offset": 0,
  6. "end_offset": 2,
  7. "type": "CN_WORD",
  8. "position": 1
  9. },
  10. {
  11. "token": "召回",
  12. "start_offset": 2,
  13. "end_offset": 4,
  14. "type": "CN_WORD",
  15. "position": 2
  16. },
  17. {
  18. "token": "筆記本",
  19. "start_offset": 4,
  20. "end_offset": 7,
  21. "type": "CN_WORD",
  22. "position": 3
  23. },
  24. {
  25. "token": "電源線",
  26. "start_offset": 7,
  27. "end_offset": 10,
  28. "type": "CN_WORD",
  29. "position": 4
  30. }
  31. ]
  32. }

 

自帶chinese和standard分詞器的結果:

 

  1. {
  2. "tokens": [
  3. {
  4. "token": "聯",
  5. "start_offset": 0,
  6. "end_offset": 1,
  7. "type": "<IDEOGRAPHIC>",
  8. "position": 1
  9. },
  10. {
  11. "token": "想",
  12. "start_offset": 1,
  13. "end_offset": 2,
  14. "type": "<IDEOGRAPHIC>",
  15. "position": 2
  16. },
  17. {
  18. "token": "召",
  19. "start_offset": 2,
  20. "end_offset": 3,
  21. "type": "<IDEOGRAPHIC>",
  22. "position": 3
  23. },
  24. {
  25. "token": "回",
  26. "start_offset": 3,
  27. "end_offset": 4,
  28. "type": "<IDEOGRAPHIC>",
  29. "position": 4
  30. },
  31. {
  32. "token": "筆",
  33. "start_offset": 4,
  34. "end_offset": 5,
  35. "type": "<IDEOGRAPHIC>",
  36. "position": 5
  37. },
  38. {
  39. "token": "記",
  40. "start_offset": 5,
  41. "end_offset": 6,
  42. "type": "<IDEOGRAPHIC>",
  43. "position": 6
  44. },
  45. {
  46. "token": "本",
  47. "start_offset": 6,
  48. "end_offset": 7,
  49. "type": "<IDEOGRAPHIC>",
  50. "position": 7
  51. },
  52. {
  53. "token": "電",
  54. "start_offset": 7,
  55. "end_offset": 8,
  56. "type": "<IDEOGRAPHIC>",
  57. "position": 8
  58. },
  59. {
  60. "token": "源",
  61. "start_offset": 8,
  62. "end_offset": 9,
  63. "type": "<IDEOGRAPHIC>",
  64. "position": 9
  65. },
  66. {
  67. "token": "線",
  68. "start_offset": 9,
  69. "end_offset": 10,
  70. "type": "<IDEOGRAPHIC>",
  71. "position": 10
  72. }
  73. ]
  74. }

 

結論沒必要多說,對於中文,官方的分詞器十分弱。

 

二、搜索關鍵詞「最新」和「fox」

測試方法:

 

  1. POST http://192.168.159.159:9200/index1/resource/_search
  2. {
  3. "query": {
  4. "multi_match": {
  5. "type": "most_fields",
  6. "query": "最新",
  7. "fields": [ "title", "title.cn", "title.en" ]
  8. }
  9. }
  10. }

 

咱們修改query 和fields 字段來對比。

1)搜索「最新」,字段限制在title.cn 的結果(只展現hit部分):

 

  1. "hits": [
  2. {
  3. "_index": "index1",
  4. "_type": "resource",
  5. "_id": "1",
  6. "_score": 1.0537746,
  7. "_source": {
  8. "title": "周星馳最新電影"
  9. }
  10. },
  11. {
  12. "_index": "index1",
  13. "_type": "resource",
  14. "_id": "3",
  15. "_score": 0.9057159,
  16. "_source": {
  17. "title": "周星馳最新電影,最好,新電影"
  18. }
  19. },
  20. {
  21. "_index": "index1",
  22. "_type": "resource",
  23. "_id": "4",
  24. "_score": 0.5319481,
  25. "_source": {
  26. "title": "最最最最好的新新新新電影"
  27. }
  28. },
  29. {
  30. "_index": "index1",
  31. "_type": "resource",
  32. "_id": "2",
  33. "_score": 0.33246756,
  34. "_source": {
  35. "title": "周星馳最好看的新電影"
  36. }
  37. }
  38. ]

 

再次搜索「最新」,字段限制在title ,title.en 的結果(只展現hit部分):

 

  1. "hits": [
  2. {
  3. "_index": "index1",
  4. "_type": "resource",
  5. "_id": "4",
  6. "_score": 1,
  7. "_source": {
  8. "title": "最最最最好的新新新新電影"
  9. }
  10. },
  11. {
  12. "_index": "index1",
  13. "_type": "resource",
  14. "_id": "1",
  15. "_score": 0.75,
  16. "_source": {
  17. "title": "周星馳最新電影"
  18. }
  19. },
  20. {
  21. "_index": "index1",
  22. "_type": "resource",
  23. "_id": "3",
  24. "_score": 0.70710677,
  25. "_source": {
  26. "title": "周星馳最新電影,最好,新電影"
  27. }
  28. },
  29. {
  30. "_index": "index1",
  31. "_type": "resource",
  32. "_id": "2",
  33. "_score": 0.625,
  34. "_source": {
  35. "title": "周星馳最好看的新電影"
  36. }
  37. }
  38. ]

 

結論:若是沒有使用ik中文分詞,會把「最新」當成兩個獨立的「字」,搜索準確性低。

 

2)搜索「fox」,字段限制在title 和title.cn ,結果爲空,對於它們兩個分詞器,fox和foxes不一樣。再次搜索「fox」,字段限制在title.en ,結果以下:

 

  1. "hits": [
  2. {
  3. "_index": "index1",
  4. "_type": "resource",
  5. "_id": "5",
  6. "_score": 0.9581454,
  7. "_source": {
  8. "title": "I'm not happy about the foxes"
  9. }
  10. }
  11. ]

 

結論:中文和標準分詞器,不對英文單詞作任何處理(單複數等),查全率低。

 

個人最佳配置

其實最開始建立的索引已是最佳配置了,在title 下增長cn 和en 兩個fields,這樣對中文,英文和其餘什麼亂七八糟文的效果都好點。就像前面說的,title 使用標準分詞器,title.cn 使用ik分詞器,title.en 使用自帶的英文分詞器,每次搜索同時覆蓋

 

 

相關文章
相關標籤/搜索