在全文搜索(Fulltext Search)中拯辙,詞(Term)是一個搜索單元丰涉,表示文本中的一個詞,標記(Token)表示在文本字段中出現(xiàn)的詞涎永,由詞的文本思币、在原始文本中的開始和結(jié)束偏移量、以及數(shù)據(jù)類型等組成羡微。ElasticSearch 把文檔數(shù)據(jù)寫到倒排索引(Inverted Index)的結(jié)構(gòu)中谷饿,倒排索引建立詞(Term)和文檔之間的映射读串,索引中的數(shù)據(jù)是面向詞狞甚,而不是面向文檔的。分析器(Analyzer)的作用就是分析(Analyse)加袋,用于把傳入Lucene的文檔數(shù)據(jù)轉(zhuǎn)化為倒排索引盯蝴,把文本處理成可被搜索的詞毅哗。
在ElasticSearch引擎中,分析器的任務是分析(Analyze)文本數(shù)據(jù)捧挺,分析是分詞虑绵,規(guī)范化文本的意思,其工作流程是:
首先松忍,字符過濾器對分析(analyzed)文本進行過濾和處理蒸殿,例如從原始文本中移除HTML標記,根據(jù)字符映射替換文本等鸣峭,
過濾之后的文本被分詞器接收宏所,分詞器把文本分割成標記流,也就是一個接一個的標記摊溶,
然后爬骤,標記過濾器對標記流進行過濾處理,例如莫换,移除停用詞霞玄,把詞轉(zhuǎn)換成其詞干形式,把詞轉(zhuǎn)換成其同義詞等拉岁,
最終坷剧,過濾之后的標記流被存儲在倒排索引中;
ElasticSearch引擎在收到用戶的查詢請求時喊暖,會使用分析器對查詢條件進行分析惫企,根據(jù)分析的結(jié)構(gòu),重新構(gòu)造查詢,以搜索倒排索引狞尔,完成全文搜索請求丛版。
無論是內(nèi)置的分析器(analyzer),還是自定義的分析器(analyzer)偏序,都由三種構(gòu)件塊組成的:**character filters 页畦,tokenizers **和 token filters。
-
**character filters **
字符過濾器以字符流的形式接收原始文本研儒,并可以通過添加豫缨、刪除或更改字符來轉(zhuǎn)換該流。
舉例來說殉摔,一個字符過濾器可以用來把阿拉伯數(shù)字(??????????)轉(zhuǎn)成成Arabic-Latin的等價物(0123456789)州胳。
一個分析器可能有0個或多個字符過濾器,它們按順序應用逸月。
-
Tokenizer (分詞器)
一個分詞器接收一個字符流,并將其拆分成單個token (通常是單個單詞)遍膜,并輸出一個token流碗硬。例如,一個whitespace分詞器當它看到空白的時候就會將文本拆分成token瓢颅。它會將文本“Quick brown fox!”轉(zhuǎn)換為[Quick, brown, fox!]
(PS:Tokenizer 負責將文本拆分成單個token 恩尾,這里token就指的就是一個一個的單詞。就是一段文本被分割成好幾部分 )
分詞器還負責記錄每個term的順序或位置挽懦,以及該term所表示的原單詞的開始和結(jié)束字符偏移量翰意。(PS:文本被分詞后的輸出是一個term數(shù)組)
一個分析器必須只能有一個分詞器
-
Token filters (token過濾器)
token過濾器接收token流,并且可能會添加信柿、刪除或更改tokens冀偶。
例如,一個lowercase token filter可以將所有的token轉(zhuǎn)成小寫渔嚷。stop token filter可以刪除常用的單詞进鸠,比如 the 。synonym token filter可以將同義詞引入token流形病。
不允許token過濾器更改每個token的位置或字符偏移量客年。
一個分析器可能有0個或多個token過濾器,它們按順序應用漠吻。
ES內(nèi)置分詞器(Tokenizer)
分詞器在字符過濾器之后工作量瓜,用于把文本分割成多個標記(Token),一個標記基本上是詞加上一些額外信息途乃,分詞器的處理結(jié)果是標記流,它是一個接一個的標記唧取,準備被過濾器處理枫弟。
-
標準分析器(Standard)
分析器類型是standard骇塘,由標準分詞器(Standard Tokenizer)韩容,標準標記過濾器(Standard Token Filter),小寫標記過濾器(Lower Case Token Filter)和停用詞標記過濾器(Stopwords Token Filter)組成插爹。參數(shù)stopwords用于初始化停用詞列表请梢,默認是空的。
-
簡單分析器(Simple)
分析器類型是simple,實際上是小寫標記分詞器(Lower Case Tokenizer)寸宵,在非字母位置上分割文本梯影,并把分詞轉(zhuǎn)換為小寫形式光酣,功能上是Letter Tokenizer和 Lower Case Token Filter的結(jié)合(Combination),但是性能更高脉课,一次性完成兩個任務唱遭。
-
空格分析器(Whitespace)
分析器類型是whitespace,實際上是空格分詞器(Whitespace Tokenizer)。
-
停用詞分析器(Stopwords)
分析器類型是stop脂矫,由小寫分詞器(Lower Case Tokenizer)和停用詞標記過濾器(Stop Token Filter)構(gòu)成庭再,配置參數(shù)stopwords或 stopwords_path指定停用詞列表颅围。
-
雪球分析器(Snowball)
分析器類型是snowball奶卓,由標準分詞器(Standard Tokenizer),標準過濾器(Standard Filter)掌猛,小寫過濾器(Lowercase Filter),停用詞過濾器(Stop Filter)和雪球過濾器(Snowball Filter)構(gòu)成孔飒。參數(shù)language用于指定語言。
-
自定義分析器
分析器類型是custom鸠匀,允許用戶定制分析器蕉斜。參數(shù)tokenizer 用于指定分詞器,filter用于指定過濾器,char_filter用于指定字符過濾器宅此。
內(nèi)置分析器實例
這里我們使用的工具是Kibana机错,我們在這里來操作一下Elasticsearch。如下的事例是ES默認的標準分析器父腕,我們使用_analyze來調(diào)試實驗一下弱匪。
POST _analyze
{
"analyzer": "standard",
"text": "I am Chinese."
}
輸出如下結(jié)果:
{
"tokens" : [
{
"token" : "i",
"start_offset" : 0,
"end_offset" : 1,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "am",
"start_offset" : 2,
"end_offset" : 4,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "chinese",
"start_offset" : 5,
"end_offset" : 12,
"type" : "<ALPHANUM>",
"position" : 2
}
]
}
而使用空格分析器的話,就會對每個空格進行分割侣诵,如下
POST _analyze
{
"analyzer": "whitespace",
"text": "I'm Chinese."
}
輸出結(jié)果:
{
"tokens" : [
{
"token" : "I'm",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "Chinese.",
"start_offset" : 4,
"end_offset" : 12,
"type" : "word",
"position" : 1
}
]
}
接下來我們創(chuàng)建一個自定義分析器:
# 創(chuàng)建一個自定義分詞器
PUT test_index_1
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_anaylzer" : {
"type" : "custom",
"tokenizer" : "standard",
"char_filter" : ["html_strip"],
"filter" : ["lowercase"]
}
}
}
}
}
以上代碼是創(chuàng)建一個自定義分析器痢法,其中使用分析器是標準分析器,字符串過濾使用的是html_strip(去除里面的html標簽內(nèi)容)杜顺,token過濾器用的是lowercase财搁,也就是把取出來的字符都轉(zhuǎn)成小寫。運行如下事例躬络。
POST test_index_1/_analyze
{
"analyzer" : "my_custom_anaylzer",
"text" : "Is this <b> a box <b>?"
}
輸出結(jié)果為:
{
"tokens" : [
{
"token" : "is",
"start_offset" : 0,
"end_offset" : 2,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "this",
"start_offset" : 3,
"end_offset" : 7,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "a",
"start_offset" : 12,
"end_offset" : 13,
"type" : "<ALPHANUM>",
"position" : 2
},
{
"token" : "box",
"start_offset" : 14,
"end_offset" : 17,
"type" : "<ALPHANUM>",
"position" : 3
}
]
}
參考
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-tokenfilters.html