這篇文章主要來介紹下什麼是 Analysis ,什麼是分詞器,以及 ElasticSearch 自帶的分詞器是怎麼工做的,最後會介紹下中文分詞是怎麼作的。html
首先來講下什麼是 Analysis:java
顧名思義,文本分析就是把全文本轉換成一系列單詞(term/token)的過程,也叫分詞。在 ES 中,Analysis 是經過分詞器(Analyzer) 來實現的,可以使用 ES 內置的分析器或者按需定製化分析器。git
舉一個分詞簡單的例子:好比你輸入 Mastering Elasticsearch
,會自動幫你分紅兩個單詞,一個是 mastering
,另外一個是 elasticsearch
,能夠看出單詞也被轉化成了小寫的。github
再簡單瞭解了 Analysis 與 Analyzer 以後,讓咱們來看下分詞器的組成:正則表達式
分詞器是專門處理分詞的組件,分詞器由如下三部分組成:elasticsearch
同時 Analyzer 三個部分也是有順序的,從圖中能夠看出,從上到下依次通過 Character Filters
,Tokenizer
以及 Token Filters
,這個順序比較好理解,一個文本進來確定要先對文本數據進行處理,再去分詞,最後對分詞的結果進行過濾。ide
其中,ES 內置了許多分詞器:工具
接下來會對以上分詞器進行講解,在講解以前先來看下頗有用的 API:_analyzer API
:學習
它能夠經過如下三種方式來查看分詞器是怎麼樣工做的:開發工具
GET _analyze { "analyzer": "standard", "text" : "Mastering Elasticsearch , elasticsearch in Action" }
POST books/_analyze { "field": "title", "text": "Mastering Elasticesearch" }
POST /_analyze { "tokenizer": "standard", "filter": ["lowercase"], "text": "Mastering Elasticesearch" }
再瞭解了 Analyzer API 後,讓咱們一塊兒看下 ES 內置的分詞器:
首先來介紹下 Stamdard Analyzer
分詞器:
它是 ES 默認的分詞器,它會對輸入的文本按詞的方式進行切分,切分好之後會進行轉小寫處理,默認的 stopwords 是關閉的。
下面使用 Kibana 看一下它是怎麼樣進行工做的,在 Kibana 的開發工具(Dev Tools)中指定 Analyzer 爲 standard
,並輸入文本 In 2020, Java is the best language in the world.
,而後咱們運行一下:
GET _analyze { "analyzer": "standard", "text": "In 2020, Java is the best language in the world." }
運行結果以下:
{ "tokens" : [ { "token" : "in", "start_offset" : 0, "end_offset" : 2, "type" : "<ALPHANUM>", "position" : 0 }, { "token" : "2020", "start_offset" : 3, "end_offset" : 7, "type" : "<NUM>", "position" : 1 }, { "token" : "java", "start_offset" : 9, "end_offset" : 13, "type" : "<ALPHANUM>", "position" : 2 }, { "token" : "is", "start_offset" : 14, "end_offset" : 16, "type" : "<ALPHANUM>", "position" : 3 }, { "token" : "the", "start_offset" : 17, "end_offset" : 20, "type" : "<ALPHANUM>", "position" : 4 }, { "token" : "best", "start_offset" : 21, "end_offset" : 25, "type" : "<ALPHANUM>", "position" : 5 }, { "token" : "language", "start_offset" : 26, "end_offset" : 34, "type" : "<ALPHANUM>", "position" : 6 }, { "token" : "in", "start_offset" : 35, "end_offset" : 37, "type" : "<ALPHANUM>", "position" : 7 }, { "token" : "the", "start_offset" : 38, "end_offset" : 41, "type" : "<ALPHANUM>", "position" : 8 }, { "token" : "world", "start_offset" : 42, "end_offset" : 47, "type" : "<ALPHANUM>", "position" : 9 } ] }
能夠看出是按照空格、非字母的方式對輸入的文本進行了轉換,好比對 Java
作了轉小寫,對一些停用詞也沒有去掉,好比 in
。
其中 token
爲分詞結果;start_offset
爲起始偏移;end_offset
爲結束偏移;position
爲分詞位置。
下面來看下 Simple Analyzer
分詞器:
它只包括了 Lower Case
的 Tokenizer
,它會按照非字母切分,非字母的會被去除,最後對切分好的作轉小寫處理,而後接着用剛纔的輸入文本,分詞器換成 simple
來進行分詞,運行結果以下:
{ "tokens" : [ { "token" : "in", "start_offset" : 0, "end_offset" : 2, "type" : "word", "position" : 0 }, { "token" : "java", "start_offset" : 9, "end_offset" : 13, "type" : "word", "position" : 1 }, { "token" : "is", "start_offset" : 14, "end_offset" : 16, "type" : "word", "position" : 2 }, { "token" : "the", "start_offset" : 17, "end_offset" : 20, "type" : "word", "position" : 3 }, { "token" : "best", "start_offset" : 21, "end_offset" : 25, "type" : "word", "position" : 4 }, { "token" : "language", "start_offset" : 26, "end_offset" : 34, "type" : "word", "position" : 5 }, { "token" : "in", "start_offset" : 35, "end_offset" : 37, "type" : "word", "position" : 6 }, { "token" : "the", "start_offset" : 38, "end_offset" : 41, "type" : "word", "position" : 7 }, { "token" : "world", "start_offset" : 42, "end_offset" : 47, "type" : "word", "position" : 8 } ] }
從結果中能夠看出,數字 2020
被去除掉了,說明非字母的的確會被去除,全部的詞也都作了小寫轉換。
如今,咱們來看下 Whitespace Analyzer
分詞器:
它很是簡單,根據名稱也能夠看出是按照空格進行切分的,下面咱們來看下它是怎麼樣工做的:
{ "tokens" : [ { "token" : "In", "start_offset" : 0, "end_offset" : 2, "type" : "word", "position" : 0 }, { "token" : "2020,", "start_offset" : 3, "end_offset" : 8, "type" : "word", "position" : 1 }, { "token" : "Java", "start_offset" : 9, "end_offset" : 13, "type" : "word", "position" : 2 }, { "token" : "is", "start_offset" : 14, "end_offset" : 16, "type" : "word", "position" : 3 }, { "token" : "the", "start_offset" : 17, "end_offset" : 20, "type" : "word", "position" : 4 }, { "token" : "best", "start_offset" : 21, "end_offset" : 25, "type" : "word", "position" : 5 }, { "token" : "language", "start_offset" : 26, "end_offset" : 34, "type" : "word", "position" : 6 }, { "token" : "in", "start_offset" : 35, "end_offset" : 37, "type" : "word", "position" : 7 }, { "token" : "the", "start_offset" : 38, "end_offset" : 41, "type" : "word", "position" : 8 }, { "token" : "world.", "start_offset" : 42, "end_offset" : 48, "type" : "word", "position" : 9 } ] }
能夠看出,只是按照空格進行切分,2020
數字仍是在的,Java
的首字母仍是大寫的,,
仍是保留的。
接下來看 Stop Analyzer
分詞器:
它由 Lowe Case
的 Tokenizer
和 Stop
的 Token Filters
組成的,相較於剛纔提到的 Simple Analyzer
,多了 stop 過濾,stop 就是會把 the
,a
,is
等修飾詞去除,一樣讓咱們看下運行結果:
{ "tokens" : [ { "token" : "java", "start_offset" : 9, "end_offset" : 13, "type" : "word", "position" : 1 }, { "token" : "best", "start_offset" : 21, "end_offset" : 25, "type" : "word", "position" : 4 }, { "token" : "language", "start_offset" : 26, "end_offset" : 34, "type" : "word", "position" : 5 }, { "token" : "world", "start_offset" : 42, "end_offset" : 47, "type" : "word", "position" : 8 } ] }
能夠看到 in
is
the
等詞都被 stop filter
過濾掉了。
接下來看下 Keyword Analyzer
:
它其實不作分詞處理,只是將輸入做爲 Term 輸出,咱們來看下運行結果:
{ "tokens" : [ { "token" : "In 2020, Java is the best language in the world.", "start_offset" : 0, "end_offset" : 48, "type" : "word", "position" : 0 } ] }
咱們能夠看到,沒有對輸入文本進行分詞,而是直接做爲 Term 輸出了。
接下來看下 Pattern Analyzer
:
它能夠經過正則表達式的方式進行分詞,默認是用 \W+
進行分割的,也就是非字母的符合進行切分的,因爲運行結果和 Stamdard Analyzer
同樣,就不展現了。
ES 爲不一樣國家語言的輸入提供了 Language Analyzer
分詞器,在裏面能夠指定不一樣的語言,咱們用 english
進行分詞看下:
{ "tokens" : [ { "token" : "2020", "start_offset" : 3, "end_offset" : 7, "type" : "<NUM>", "position" : 1 }, { "token" : "java", "start_offset" : 9, "end_offset" : 13, "type" : "<ALPHANUM>", "position" : 2 }, { "token" : "best", "start_offset" : 21, "end_offset" : 25, "type" : "<ALPHANUM>", "position" : 5 }, { "token" : "languag", "start_offset" : 26, "end_offset" : 34, "type" : "<ALPHANUM>", "position" : 6 }, { "token" : "world", "start_offset" : 42, "end_offset" : 47, "type" : "<ALPHANUM>", "position" : 9 } ] }
能夠看出 language
被改爲了 languag
,同時它也是有 stop 過濾器的,好比 in
,is
等詞也被去除了。
最後,讓咱們看下中文分詞:
中文分詞有特定的難點,不像英文,單詞有天然的空格做爲分隔,在中文句子中,不能簡單地切分紅一個個的字,而是須要分紅有含義的詞,可是在不一樣的上下文,是有不一樣的理解的。
好比如下例子:
在這些,企業中,國有,企業,有十個/在這些,企業,中國,有企業,有十個 各國,有,企業,相繼,倒閉/各,國有,企業,相繼,倒閉 羽毛球,拍賣,完了/羽毛球拍,賣,完了
那麼,讓咱們來看下 ICU Analyzer
分詞器,它提供了 Unicode 的支持,更好的支持亞洲語言!
咱們先用 standard
來分詞,以便於和 ICU 進行對比。
GET _analyze { "analyzer": "standard", "text": "各國有企業相繼倒閉" }
運行結果就不展現了,分詞是一個字一個字切分的,明顯效果不是很好,接下來用 ICU 進行分詞,分詞結果以下:
{ "tokens" : [ { "token" : "各國", "start_offset" : 0, "end_offset" : 2, "type" : "<IDEOGRAPHIC>", "position" : 0 }, { "token" : "有", "start_offset" : 2, "end_offset" : 3, "type" : "<IDEOGRAPHIC>", "position" : 1 }, { "token" : "企業", "start_offset" : 3, "end_offset" : 5, "type" : "<IDEOGRAPHIC>", "position" : 2 }, { "token" : "相繼", "start_offset" : 5, "end_offset" : 7, "type" : "<IDEOGRAPHIC>", "position" : 3 }, { "token" : "倒閉", "start_offset" : 7, "end_offset" : 9, "type" : "<IDEOGRAPHIC>", "position" : 4 } ] }
能夠看到分紅了各國
,有
,企業
,相繼
,倒閉
,顯然比剛纔的效果好了不少。
還有許多中文分詞器,在這裏列舉幾個:
IK:
jieba:
THULAC:
你們能夠本身安裝下,看下它中文分詞效果。
本文主要介紹了 ElasticSearch 自帶的分詞器,學習了使用 _analyzer API
去查看它的分詞狀況,最後還介紹下中文分詞是怎麼作的。
參考文獻
Elasticsearch頂尖高手系列
Elasticsearch核心技術與實戰
https://www.elastic.co/guide/en/elasticsearch/reference/7.1/indices-analyze.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer-anatomy.html