1. 程式人生 > >[ES]elasticsearch章5 ES的分詞(二)

[ES]elasticsearch章5 ES的分詞(二)

string tor 會同 需要 分隔 clas c中 ken fig

Elasticsearch 中文搜索時遇到幾個問題:

    1. 當搜索關鍵詞如:“人民幣”時,如果分詞將“人民幣”分成“人”,“民”,“幣”三個單字,那麽搜索該關鍵詞會匹配到很多包含該單字的無關內容,但是如果將該詞分詞成一個整詞“人民幣”,搜索單字如“人”字又不會匹配到包含“人民幣”關鍵詞的內容,怎麽解決這個問題,既保證覆蓋度又保證準確度?
    1. 搜索“RMB”時只會匹配到包含“RMB”關鍵詞的內容,實際上,“RMB”和“人民幣”是同義詞,我們希望用戶搜索“RMB”和“人民幣”可以相互匹配,ES同義詞怎麽配置?

接下來從以下幾點講一下怎麽ES中文分詞

  1. 中文分詞器
  2. ES 分詞流程之 analysis,analyzer,filter,tokenizer
  3. ES內置分詞器
  4. 自定義analyzer
  5. ES同義詞功能實現

1.IK 分詞器

  • 1,Elasticsearch中文分詞我們采用Ik分詞,ik有兩種分詞模式,ik_max_word,和ik_smart模式;
    • ik_max_word 和 ik_smart 什麽區別?

ik_max_word: 會將文本做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合;

ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,國歌”。

索引時,為了提供索引的覆蓋範圍,通常會采用ik_max_word分析器,會以最細粒度分詞索引,搜索時為了提高搜索準確度,會采用ik_smart分析器,會以粗粒度分詞
字段mapping設置如下:

    "author": {
            "type": "string",
            "analyzer": "ik",
            "search_analyzer": "ik_smart"
        }

2.Elasticsearch之分析(analysis)和分析器(analyzer)

analysis索引分析模塊充當analyzer分析器的可配置註冊表,通過analyzer對文檔索引階段的字段和搜索String進行處理,自定義analyzer時,通常需要character filter tokenizer token filters來完成

2.1 character filter 字符過濾器

首先字符串經過過濾器(character filter),他們的工作是在分詞前處理字符串。字符過濾器能夠去除HTML標記,例如把“<a>”變成“a

2.2 tokenizer 分詞器

英文分詞可以根據空格將單詞分開,中文分詞比較復雜,可以采用機器學習算法來分詞

2.2 token filters 表征過濾器

最後,每個詞都通過所有表征過濾(token filters),他可以修改詞(例如將“Quick”轉為小寫),去掉詞(例如停用詞像“a”、“and”、“the”等等),或者增加詞(例如同義詞像“a”、“and”、“the”等等)或者增加詞(例如同義詞像“jump”和“leap”)。

2.3 ES分詞流程

character filter-->>tokenizer-->>token filters

2.5 自定義analyzer

官網example:

index :
    analysis :
        analyzer :
            myAnalyzer2 :
                type : custom
                tokenizer : myTokenizer1
                filter : [myTokenFilter1, myTokenFilter2]
                char_filter : [my_html]
                position_increment_gap: 256
        tokenizer :
            myTokenizer1 :
                type : standard
                max_token_length : 900
        filter :
            myTokenFilter1 :
                type : stop
                stopwords : [stop1, stop2, stop3, stop4]
            myTokenFilter2 :
                type : length
                min : 0
                max : 2000
        char_filter :
              my_html :
                type : html_strip
                escaped_tags : [xxx, yyy]
                read_ahead : 1024
2.6 分詞mapping設置

通常為了保證索引時覆蓋度和搜索時準確度,索引分詞器采用ik_max_word,搜索分析器采用ik_smart模式

"content": {
          "type": "string",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_smart"
        }
1.7 如果更改了mapping分詞器,需要重新索引數據才能生效
POST /_reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}

因為倒排索引中的數據是索引時由分詞器來處理的,如果分詞器有變化,那麽搜索時query關鍵詞即使和doc中關鍵詞相同,但是因為分詞器的原因,分出來的詞會出現不匹配的情況,因此當mapping或者分詞器字典同義詞詞典等發生變化時,需要reindex索引數據

1.8 更改別名,不重啟服務切換索引
POST /_aliases

{  
  "actions": [  
    {  
      "remove": {  
        "index": "oldindex",  
        "alias": "alias_oldindex"  
      }  
    },  
    {  
      "add": {  
        "index": "newindex",  
        "alias": "alias_oldindex"  
      }  
    }  
  ]  
}

2 同義詞

2.1 建議同義詞詞典

  • elasticsearch /config/analysis 下建議同義詞詞典文件pro_synonym.txt,采用UTF-8編碼,寫入內容
  • 同義詞內容格式 ,註意標點符號使用英文符號
    • 啟航 => 起航 : "=>"左邊的詞全部會被右邊的詞替換
    • 啟航,起航 :使用","英文逗號分隔,兩個詞是互等的,分詞時會同時分成兩個詞進行索引或者檢索,如"啟航"會被分成"啟航","起航"兩個詞分別建立索引或者去倒排索引檢索

自定義添加同義詞通過ik分詞器

"settings": {
        "analysis": {
            "filter": {
                "my_synonym_filter": {
                    "type": "synonym",
                    "synonyms_path": "analysis/pro_synonym.txt"
                }
            },
            "analyzer": {
                "ik_syno_max_word": {
                    "tokenizer": "ik",
                    "filter": "my_synonym_filter"
                },
                "ik_syno_smart": {
                    "tokenizer": "ik_smart",
                    "filter": "my_synonym_filter"
                }
            }
        }
    }

想查看同義詞效果或者測試分詞效果

3 Suggest分詞

suggest詞需要對拼音前綴,全拼,中文進行前綴匹配,例如:“百度”一詞,鍵入"baidu","bd","百"都必須匹配到,因此在索引的時候需要一詞分多個分詞器來索引保存,中文采用單字分詞,拼音首字母和全拼需要自定義analyzer來索引。

  • Elasticsearch Suggest setting mapping設置參考如下
{
    "mappings": {
        "suggest": {
            "properties": {
                "full_pinyin": {
                    "type": "completion",
                    "analyzer": "full_pinyin_analyzer",
                    "payloads": true,
                    "preserve_separators": false,
                    "preserve_position_increments": true,
                    "max_input_length": 50
                },
                "prefix_pinyin": {
                    "type": "completion",
                    "analyzer": "prefix_pinyin_analyzer",
                    "search_analyzer": "standard",
                    "payloads": true,
                    "preserve_separators": false,
                    "preserve_position_increments": true,
                    "max_input_length": 50
                },
                "suggestText": {
                    "type": "completion",
                    "analyzer": "standard",
                    "payloads": true,
                    "preserve_separators": false,
                    "preserve_position_increments": true,
                    "max_input_length": 50
                }
            }
        }
    },
    "settings": {
        "index": {
            "analysis": {
                "filter": {
                    "_pattern": {
                        "type": "pattern_capture",
                        "preserve_original": "1",
                        "patterns": ["([0-9])", "([a-z])"]
                    },
                    "full_pinyin": {
                        "keep_first_letter": "false",
                        "keep_none_chinese_in_first_letter": "false",
                        "type": "pinyin",
                        "keep_original": "false",
                        "keep_full_pinyin": "true"
                    },
                    "prefix_pinyin": {
                        "keep_first_letter": "true",
                        "none_chinese_pinyin_tokenize": "false",
                        "type": "pinyin",
                        "keep_original": "false",
                        "keep_full_pinyin": "false"
                    }
                },
                "analyzer": {
                    "full_pinyin_analyzer": {
                        "filter": ["lowercase", "full_pinyin"],
                        "tokenizer": "standard"
                    },
                    "prefix_pinyin_analyzer": {
                        "filter": ["lowercase", "prefix_pinyin"],
                        "tokenizer": "standard"
                    }
                }
            }
        }
    }
}

關於搜索關鍵詞會將不相關詞搜索出來

  • 解決單字搜索的一種方案
    • 問題:搜索時,搜索牙膏,需檢索出包含“牙膏”二字的內容,過濾掉包含“牙”或者“膏”的內容,但是搜索單字“牙”或者“膏”時需要將牙膏匹配出來
    • 方案:加入單字字典,ik_max_word分詞時,會把所有形式分出來,因此單字字典,此分詞模式下會將單字索引起來,ik_smart會按照最粗粒度分詞,搜索關鍵詞時不會匹配單字內容
    • 索引和搜索采用不同分詞器 "analyzer": "ik", "search_analyzer": "ik_smart"
    • 過程:更改mapping,searchAnalyzer=ik_smart

[ES]elasticsearch章5 ES的分詞(二)