elasticsearch 深刻 —— 分析器

參考:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.htmljavascript

在全文搜索(Fulltext Search)中,詞(Term)是一個搜索單元,表示文本中的一個詞,標記(Token)表示在文本字段中出現的詞,由詞的文本、在原始文本中的開始和結束偏移量、以及數據類型等組成。ElasticSearch 把文檔數據寫到倒排索引(Inverted Index)的結構中,倒排索引創建詞(Term)和文檔之間的映射,索引中的數據是面向詞,而不是面向文檔的。分析器(Analyzer)的做用就是分析(Analyse),用於把傳入Lucene的文檔數據轉化爲倒排索引,把文本處理成可被搜索的詞。分析器由一個分詞器(Tokenizer)和零個或多個標記過濾器(TokenFilter)組成,也能夠包含零個或多個字符過濾器(Character Filter)。html

在ElasticSearch引擎中,分析器的任務是分析(Analyze)文本數據,分析是分詞,規範化文本的意思,其工做流程是:java

  • 首先,字符過濾器對分析(analyzed)文本進行過濾和處理,例如從原始文本中移除HTML標記,根據字符映射替換文本等,
  • 過濾以後的文本被分詞器接收,分詞器把文本分割成標記流,也就是一個接一個的標記,
  • 而後,標記過濾器對標記流進行過濾處理,例如,移除停用詞,把詞轉換成其詞幹形式,把詞轉換成其同義詞等,
  • 最終,過濾以後的標記流被存儲在倒排索引中;
  • ElasticSearch引擎在收到用戶的查詢請求時,會使用分析器對查詢條件進行分析,根據分析的結構,從新構造查詢,以搜索倒排索引,完成全文搜索請求,

可見,分析器扮演的是處理索引數據和查詢條件的重要角色。在2.4版本中,ElasticSearch 預約義了7個分析器,而且支持用戶根據預約義的字符過濾器,分詞器和標記過濾器建立自定義的分析器,以知足用戶多樣性的文本分析需求。c++

用戶在建立索引時配置索引的分析,經過向ElasticSearch發送請求,在請求body的settings 配置節中設置索引的分析器,例如,爲索引配置默認的分析器:正則表達式

{
    "settings": {
        "index": {
            "analysis": {
                "analyzer": {
                    "default": {
                        "type": "standard",
                        "stopwords": "_english_"
                    }
                }
            }
        }
    }
}

一,字符過濾器(Char Filter)算法

字符過濾器對未經分析的文本起做用,做用於被分析的文本字段(該字段的index屬性爲analyzed),字符過濾器在分詞器以前工做,用於從文檔的原始文本去除HTML標記(markup),或者把字符「&」轉換爲單詞「and」。ElasticSearch 2.4版本內置3個字符過濾器,分別是:映射字符過濾器(Mapping Char Filter)、HTML標記字符過濾器(HTML Strip Char Filter)和模式替換字符過濾器(Pattern Replace Char Filter)。c#

1,映射字符過濾器api

映射字符過濾器,類型是mapping,須要創建一個查找字符和替換字符的映射(Mapping),過濾器根據映射把文本中的字符替換成指定的字符。app

PUT /my_index

{
    "index" : {
        "analysis" : {
            "char_filter" : {
                "my_mapping" : {
                    "type" : "mapping",
                    "mappings" : [
                      "c# => csharp",
                      "c++ => cplus"
                    ]
                }
            },
            "analyzer" : {
                "custom_with_char_filter" : {
                    "tokenizer" : "standard",
                    "char_filter" : ["my_mapping"]
                }
            }
        }
    }
}

或

{
    "settings": {
        "analysis": {
            "char_filter": {
                "mapping_filter": {
                    "type": "mapping",
                    "mappings": [
                      "c# => csharp",
                      "c++ => cplus"
                  ]
                }
            }
        }
    }
}

也能夠經過文件載入字符映射表elasticsearch

PUT /my_index
{
    "settings": {
        "analysis": {
            "char_filter": {
                "mapping_filter": {
                    "type": "mapping",
                    "mappings_path": "mappings.txt"
                }
            }
        }
    }
}

2,HTML標記字符過濾器

HTML標記字符過濾器,類型是html_strip,用於從原始文本中去除HTML標記,例如「<a>」就會變成「a」。

3,模式替換字符過濾器

模式替換字符過濾器,類型是pattern_replace,它使用正則表達式(Regular Expression)匹配字符,把匹配到的字符替換爲指定的替換字符串。

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "standard",
          "char_filter": [
            "my_char_filter"
          ]
        }
      },
      "char_filter": {
        "my_char_filter": {
          "type": "pattern_replace",
          "pattern": "(\\d+)-(?=\\d)",
          "replacement": "$1_"
        }
      }
    }
  }
}

pattern參數:指定Java正則表達式;

replacement參數:指定替換字符串,把正則表達式匹配的字符串替換爲replacement參數指定的字符串;

二,分詞器(Tokenizer)

分詞器在字符過濾器以後工做,用於把文本分割成多個標記(Token),一個標記基本上是詞加上一些額外信息,分詞器的處理結果是標記流,它是一個接一個的標記,準備被過濾器處理。ElasticSearch 2.4版本內置不少分詞器,本節簡單介紹經常使用的分詞器。

1,標準分詞器(Standard Tokenizer)

標準分詞器類型是standard,用於大多數歐洲語言,使用Unicode文本分割算法對文檔進行分詞。

2,字母分詞器(Letter Tokenizer)

字符分詞器類型是letter,在非字母位置上分割文本,這就是說,根據相鄰的詞之間是否存在非字母(例如空格,逗號等)的字符,對文本進行分詞,對大多數歐洲語言很是有用。

3,空格分詞器(Whitespace Tokenizer)

空格分詞類型是whitespace,在空格處分割文本

4,小寫分詞器(Lowercase Tokenizer)

小寫分詞器類型是lowercase,在非字母位置上分割文本,並把分詞轉換爲小寫形式,功能上是Letter Tokenizer和 Lower Case Token Filter的結合(Combination),可是性能更高,一次性完成兩個任務。

5,經典分詞器(Classic Tokenizer)

經典分詞器類型是classic,基於語法規則對文本進行分詞,對英語文檔分詞很是有用,在處理首字母縮寫,公司名稱,郵件地址和Internet主機名上效果很是好。

三,標記過濾器(Token Filter)

分析器包含零個或多個標記過濾器,標記過濾器在分詞器以後工做,用來處理標記流中的標記。標記過濾從分詞器中接收標記流,可以刪除標記,轉換標記,或添加標記。ElasticSearch 2.4版本內置不少標記過濾器,本節簡單介紹經常使用的過濾器。

1,小寫標記過濾器(Lowercase)

類型是lowercase,用於把標記轉換爲小寫形式,經過language參數指定語言,小寫標記過濾器支持的語言有:Greek, Irish, and Turkish

PUT index
{
  "settings": {
    "analysis": {
      "normalizer": {
        "my_normalizer": {
          "type": "custom",
          "char_filter": [],
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  },
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "keyword",
          "normalizer": "my_normalizer"
        }
      }
    }
  }
}

參考:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/normalizer.html

2,停用詞標記過濾器(Stopwords)

類型是stop,用於從標記流中移除停用詞。參數stopwords用於指定停用詞,ElasticSearch 2.4版本提供的預約義的停用詞列表:預約義的英語停用詞是_english_,使用預約義的英語停用詞列表是  「stopwords」 :"_english_"

PUT /my_index
{
    "settings": {
        "analysis": {
            "filter": {
                "my_stop": {
                    "type":       "stop",
                    "stopwords": ["and", "is", "the"]
                }
            }
        }
    }
}

3,詞幹過濾器(Stemmer)

類型是stemmer,用於把詞轉換爲其詞根形式存儲在倒排索引,可以減小標記。

{
    "index" : {
        "analysis" : {
            "analyzer" : {
                "my_analyzer" : {
                    "tokenizer" : "standard",
                    "filter" : ["standard", "lowercase", "my_stemmer"]
                }
            },
            "filter" : {
                "my_stemmer" : {
                    "type" : "stemmer",
                    "name" : "english"
                }
            }
        }
    }
}

4,同義詞過濾器(Synonym)

類型是synonym,在分析階段,基於同義詞規則,把詞轉換爲其同義詞存儲在倒排索引中

{
    "index" : {
        "analysis" : {
            "analyzer" : {
                "synonym" : {
                    "tokenizer" : "whitespace",
                    "filter" : ["synonym"]
                }
            },
            "filter" : {
                "synonym" : {
                    "type" : "synonym",
                    "synonyms_path" : "analysis/synonym.txt"
                }
            }
        }
    }
}

同義詞文件的格式示例:

# Blank lines and lines starting with pound are comments.

# Explicit mappings match any token sequence on the LHS of "=>"
# and replace with all alternatives on the RHS.  These types of mappings
# ignore the expand parameter in the schema.
# Examples:
i-pod, i pod => ipod,
sea biscuit, sea biscit => seabiscuit

# Equivalent synonyms may be separated with commas and give
# no explicit mapping.  In this case the mapping behavior will
# be taken from the expand parameter in the schema.  This allows
# the same synonym file to be used in different synonym handling strategies.
# Examples:
ipod, i-pod, i pod
foozball , foosball
universe , cosmos

# If expand==true, "ipod, i-pod, i pod" is equivalent
# to the explicit mapping:
ipod, i-pod, i pod => ipod, i-pod, i pod
# If expand==false, "ipod, i-pod, i pod" is equivalent
# to the explicit mapping:
ipod, i-pod, i pod => ipod

# Multiple synonym mapping entries are merged.
foo => foo bar
foo => baz
# is equivalent to
foo => foo bar, baz

四,系統預約義的分析器

在建立索引映射時引用分析器,若是沒有定義分析器,那麼ElasticSearch將使用默認的分析器,用戶能夠經過API設置默認的分析器。

default 邏輯名稱用於配置在索引和搜索時使用的分析器,default_search 邏輯名稱用於配置在搜索時使用的分析器。

index :
  analysis :
    analyzer :
      default :
        tokenizer : keyword

1,標準分析器(Standard)

分析器類型是standard,由標準分詞器(Standard Tokenizer),標準標記過濾器(Standard Token Filter),小寫標記過濾器(Lower Case Token Filter)和停用詞標記過濾器(Stopwords Token Filter)組成。參數stopwords用於初始化停用詞列表,默認是空的。

2,簡單分析器(Simple)

分析器類型是simple,其實是小寫標記分詞器(Lower Case Tokenizer),在非字母位置上分割文本,並把分詞轉換爲小寫形式,功能上是Letter Tokenizer和 Lower Case Token Filter的結合(Combination),可是性能更高,一次性完成兩個任務。

3,空格分析器(Whitespace)

分析器類型是whitespace,其實是空格分詞器(Whitespace Tokenizer)。

4,停用詞分析器(Stopwords)

分析器類型是stop,由小寫分詞器(Lower Case Tokenizer)和停用詞標記過濾器(Stop Token Filter)構成,配置參數stopwords 或 stopwords_path指定停用詞列表。

5,雪球分析器(Snowball)

分析器類型是snowball,由標準分詞器(Standard Tokenizer),標準過濾器(Standard Filter),小寫過濾器(Lowercase Filter),停用詞過濾器(Stop Filter)和雪球過濾器(Snowball Filter)構成。參數language用於指定語言。

{
    "index" : {
        "analysis" : {
            "analyzer" : {
                "my_analyzer" : {
                    "type" : "snowball",
                    "language" : "English"
                }
            }
        }
    }
}

6,自定義分析器

ES內置了不少Analyzer, 還有不少第三方的Analyzer插件, 好比一些處理中文的Analyzer(中文分詞)。 
analyzer、 tokenizer、 filter能夠在elasticsearch.yml 配置, 下面是配置例子

分析器類型是custom,容許用戶定製分析器。參數tokenizer 用於指定分詞器,filter用於指定過濾器,char_filter用於指定字符過濾器。

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
PUT /my_index
{
    "settings": {
        "analysis": {
            "char_filter": {
                "&_to_and": {
                    "type":       "mapping",
                    "mappings": [ "& => and "]
            }},
            "filter": {
                "my_stopwords": {
                    "type":       "stop",
                    "stopwords": [ "the", "a" ]
            }},
            "analyzer": {
                "my_analyzer": {
                    "type":         "custom",
                    "char_filter":  [ "html_strip", "&_to_and" ],
                    "tokenizer":    "standard",
                    "filter":       [ "lowercase", "my_stopwords" ]
            }}
        } 
    }
}

參照:

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-custom-analyzer.html

https://www.jianshu.com/p/5b6cd1165383

https://www.biaodianfu.com/elasticsearch-install-chinese-segmenter-plugin.html

https://www.cnblogs.com/qindongliang/p/4989525.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenizers.html

五,查詢分析

在分析(_ayalyze)端點上執行分析查詢,用於對查詢參數進行分析,並返回分析的結果

1,使用默認的分析器執行查詢分析

例如,在索引ebrite上執行分析查詢,分析字符「After School」,從返回的結果中,能夠看到兩個標記(Token):「after」和「school」,類型(type)是字符數字類型(<ALPHANUM>),偏移量(offset)從1開始計數,位置(position)從0開始計數。

POST myindex/_analyze -d
"After School"

2,指定分析器

POST myindex/_analyze?analyzer=standard -d
"After School"

3,指定分詞器和過濾器

POST myindex/_analyze?tokenizer=standard&filters=lowercase -d
"After School"

4,在特定的字段上執行分析查詢

POST myindex/_analyze?field=doc_field&tokenizer=standard&filters=lowercase -d
"After School"

附,在建立索引時,指定默認的分析器

示例代碼,使用PUT動詞,在建立索引時指定默認的分析器,ElasticSearch引擎在索引文檔時,使用默認的分析器對index屬性爲analyzed的文本字段執行分析操做,而非分析字段,將不會應用分析操做。

{  
   "settings":{  
      "number_of_shards":5,
      "number_of_replicas":0,
      "index":{
        "analysis":{
            "analyzer":{
                "default":{
                    "type":"standard"
                    ,"stopwords":"_english_"
                }
            }
        }
      }
   },
   "mappings":{  
      "events":{  
         "dynamic":"false",
         "properties":{  
            "eventid":{  
               "type":"long",
               "store":false,
               "index":"not_analyzed"
            },
            "eventname":{  
               "type":"string",
               "store":false,
               "index":"analyzed",
               "fields":{  
                  "raw":{  
                     "type":"string",
                     "store":false,
                     "index":"not_analyzed"
                  }
               }
            }
         }
      }
   }
}

參考文檔:

Elasticsearch: Analyzing Text with the Analyze API

Elasticsearch: The Definitive Guide [2.x] » Dealing with Human Language

Elasticsearch Reference [2.4] » Analysis