1 索引的分析
索引分析: 就是把輸入的文本塊按照一定的策略進行分解, 並建立倒排索引的過程. 在Lucene的架構中, 這個過程由分析器(analyzer)完成.
1.1 分析器的組成
① 字符過濾器(character filter): 比如去除HTML標簽、把&
替換為and
等.
② 分詞器(tokenizer): 按照某種規律, 如根據空格、逗號等, 將文本塊進行分解.
③ 標記過濾器(token filter): 所有被分詞器分解的詞都將經過token filters的處理, 它可以修改詞(如小寫化處理)、去掉詞(根據某一規則去掉無意義的詞, 如"a", "the", "的"等), 增加詞(如同義詞"jump"、"leap"等).
注意: 人們一般將分析器通稱為分詞器, 並不是相等的關系, 而是包含的關系.
1.2 倒排索引的核心原理-normalization
建立倒排索引時, 會執行normalization
(正常化)操作 —— 將拆分的各個單詞進行處理, 以提高搜索時命中關聯的文檔的概率.
normalization的方式有: 時態轉換, 單復數轉換, 同義詞轉換, 大小寫轉換等.
比如文檔中包含
His mom likes small dogs
:
① 在建立索引的時候normalization會對文檔進行時態、單復數、同義詞等方面的處理;
② 然后用戶通過近似的mother liked little dog
, 也能搜索到相關的文檔.
2 ES的默認分詞器
(1) ES中的默認分詞器: standard tokenizer, 是標准分詞器, 它以單詞為邊界進行分詞. 具有如下功能:
① standard token filter: 去掉無意義的標簽, 如<>, &, - 等.
② lowercase token filter: 將所有字母轉換為小寫字母.
③ stop token filer(默認被禁用): 移除停用詞, 比如"a"、"the"等.
(2) 測試默認分詞器:
GET _analyze // ES引擎中已有standard分詞器, 所以可以不指定index
{
"analyzer": "standard",
"text": "There-is & a DOG<br/> in house"
}
可以發現, Elasticsearch對text文本進行了分析處理, 結果如下:
{
"tokens" : [
{
"token" : "there", // 分詞
"start_offset" : 0, // 起始偏移量
"end_offset" : 5, // 結束偏移量
"type" : "<ALPHANUM>", // 分詞的類型
"position" : 0 // 該分詞在文本中的位置
},
{
"token" : "is",
"start_offset" : 6,
"end_offset" : 8,
"type" : "<ALPHANUM>",
"position" : 1
},
{
"token" : "a",
"start_offset" : 11,
"end_offset" : 12,
"type" : "<ALPHANUM>",
"position" : 2
},
// 省略其他4項
]
}
3 修改分詞器
(1) 創建索引后可以添加新的分詞器:
說明: 必須先關閉索引, 添加完成后, 再及時打開索引進行搜索等操作, 否則將出現錯誤.
// 關閉索引:
POST address/_close
// 啟用English停用詞token filter
PUT address/_settings
{
"analysis": {
"analyzer": {
"my_token_filter": { // 自定義的分詞器名稱
"type": "standard",
"stopwords": "_english_"
}
}
}
}
// 打開索引:
POST address/_open
(2) 使用具有停詞功能的分詞器進行分詞:
GET address/_analyze // 指定索引
{
"analyzer": "my_token_filter", // 指定要使用的分詞器
"text": "There-is & a DOG<br/> in house"
}
(3) 返回結果減少了停用詞there
, is
, &
, a
, in
等:
{
"tokens" : [
{
"token" : "dog",
"start_offset" : 13,
"end_offset" : 16,
"type" : "<ALPHANUM>",
"position" : 3
},
{
"token" : "br",
"start_offset" : 17,
"end_offset" : 19,
"type" : "<ALPHANUM>",
"position" : 4
},
{
"token" : "house",
"start_offset" : 25,
"end_offset" : 30,
"type" : "<ALPHANUM>",
"position" : 6
}
]
}
4 定制分詞器
4.1 向索引中添加自定義的分詞器
同樣的, 在添加新的分詞器之前, 必須先關閉索引, 添加完成后, 再打開索引進行搜索等操作.
PUT address/_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"], // 跳過HTML標簽, 將&符號轉換為"and"
"tokenizer": "standard",
"filter": ["lowercase", "my_stopwords"] // 轉換為小寫
}
}
}
}
4.2 測試自定義分析器
GET address/_analyze
{
"analyzer": "my_analyzer", // 上面定義的分析器名稱
"text": "There-is & a DOG<br/> in house"
}
可以發現, 返回的分析結果中已經對大寫單詞、HTML標簽, 以及"&"做了處理.
{
"tokens" : [
// there和is
{
"token" : "and", // &被處理成了and
"start_offset" : 9,
"end_offset" : 10,
"type" : "<ALPHANUM>",
"position" : 2
},
// dog、in和house
]
}
4.3 向映射中添加自定義的分詞器
PUT address/_mapping/province
{
"properties": {
"content": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
此時查看mapping信息:
GET address/_mapping
發現自定義的分析器已經配置到province上了:
{
"address": {
"mappings": {
"province": {
"properties": {
"area" : {
"type" : "float"
},
"content" : {
"type" : "text",
"analyzer" : "my_analyzer"
},
"name" : {
"type" : "text"
}
}
}
}
}
}
5 常見問題
在修改索引之前, 沒有關閉索引, 修改時發生如下錯誤:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Can't update non dynamic settings [[index.analysis.analyzer.my_token_filter.type, index.analysis.analyzer.my_token_filter.stopwords]] for open indices [[address/Ci6MJV4sTyuoF4r9aLvVZg]]"
}
],
"type": "illegal_argument_exception",
"reason": "Can't update non dynamic settings [[index.analysis.analyzer.my_token_filter.type, index.analysis.analyzer.my_token_filter.stopwords]] for open indices [[address/Ci6MJV4sTyuoF4r9aLvVZg]]"
},
"status": 400
}
查看本篇第[3]節的說明, 先關閉索引再執行修改操作.
版權聲明
出處: 博客園 馬瘦風的博客(https://www.cnblogs.com/shoufeng)
感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜
本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文鏈接], 否則博主保留追究相關人員法律責任的權利.