分析是將文本,如任何電子郵件的正文轉換成附加到反向索引的tokens(標記)或terms(條件)的過程。分析由分析器執行,它可以是內置的分析器,也可以是每個索引定義的自定義分析器。
索引時分析
在索引時,內置的english analyzer(英文分析器)將會轉換這個句子:
"The QUICK brown foxes jumped over the lazy dog!"
這些條件將被添加到反向索引中。
[ quick, brown, fox, jump, over, lazi, dog ]
Elastic Search內置了好幾種分析器,我們可以指定字段使用的分析器,在mapping的時候設置analyzer字段即可。
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard"
}
}
}
}
在索引時,如果沒有指定分析器,則會在索引設置中查找名為default的分析器。未找到則默認使用standard analyzer(標准分析器)。
搜索時分析
例如,用戶可能搜索:
"a quick fox"
這將由類似英語分析器分析為以下的條件:
[ quick, fox ]
通常在索引時和搜索時應該使用相同的分析器,而像match query(匹配查詢)那樣的全文檢索將使用映射來查找用於每個字段的分析器。
搜索時字段分析器可以有多種途徑指定:
-
在查詢中指定分析器。
-
search_analyzer映射參數。
-
analyzer映射參數。
搜索的時候會按照上述優先級使用分析器。
常用分詞器
標准分詞器
在默認情況下,Elasticsearch使用標注分詞器進行分詞,它根據 Unicode 聯盟 定義的 單詞邊界 划分文本。刪除絕大部分標點。最后,將詞條小寫。例如,對於如下文本:
"Set the shape to semi-transparent by calling set_trans(5)"
它會產生set, the, shape, to, semi, transparent, by, calling, set_trans, 5這些分詞。對於英文語言來說使用還是非常實用的。
IK分詞器
標准分詞器對於英文還是非常方便的,但是對於中文卻不行,會將中文拆成一個個的單字,搜索效率和精度都不行,這是就需要用一些第三方中文分詞器,常見的是IK分詞器。
使用IK分詞器,首先需要安裝IK分詞器插件:
$ ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.2.0/elasticsearch-analysis-ik-7.2.0.zip
需要注意的時,必須選擇和ElasticSearch一致的版本。
然后在映射中指定索引分析器和搜索分析器即可:
"properties": {
"user": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
NGram分詞器
前面的分詞器主要應用場景是全文搜索,但對於模糊搜索的場景就不行了,雖然ElasticSearch也提供wildcard查詢和正則表達式查詢能實現模糊搜索。但是他們的性能是非常低下的,如果對性能有要求基本上可以拋棄他們了。
一個簡單的解決方案是使用ngram分詞器,然后使用match_phrase來匹配,
具體原理我就不介紹了,可以參考如下幾篇文章:
自定義分詞
除了標准的分詞器外,我們有事還要用到自定義分詞器,或者設置分詞器的一些參數,這個時候就需要一些高級設置了,一個簡單的示例如下:
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
}
簡單的來講,就是在setting中設置分詞器參數,然后在mapping中使用分詞器,具體用法可以參看官方文檔:Create a custom analyzer
測試分詞器
有些時候很難理解分詞的過程和實際被存儲到索引中的詞條,特別是你剛接觸Elasticsearch。為了理解發生了什么,你可以使用 analyze API 來看文本是如何被分析的。在消息體里,指定分析器和要分析的文本:
GET /_analyze
{
"analyzer": "standard",
"text": "Text to analyze"
}
對於索引里面的自定義分詞器,可以帶上索引名稱:
POST /my_index/_analyze
{
"analyzer": "my_analyzer",
"text": "2 Quick Foxes."
}