Elasticsearch的分析和對映
1.確切值(Exact values) vs 全文文字(Full text)
Elasticsearch中索引的資料可以大致分為兩種型別
(1) 確切值(Exact values)
確切值是需要精準匹配的值。比如一個date或使用者ID,對於2019-11-8,只輸入2019-11是不能被檢索出來。
(2) 全文文字(Full text)
對於全文文字,Elasticsearch會對文字分析(analyzes),然後使用結果建立一個倒排索引,可以支援模糊匹配,忽略大小寫,近義詞匹配等。
2.Elasticsearch分析器
什麼時候使用分析器?
當我們索引一個文件,它的全文域被分析成詞條以用來建立倒排索引。同時,當我們在全文域搜尋 的時候,將查詢字串也需要通過相同的分析過程 ,以保證我們搜尋的詞條格式與索引中的詞條格式一致。
- 當你查詢一個全文域時, 會對查詢字串應用相同的分析器,以產生正確的搜尋詞條列表。
- 當你查詢一個精確值域時,不會分析查詢字串,而是搜尋你指定的精確值。
Elasticsearch的分析器組成
es的分析器由3部分組成:
(1)字元過濾器(character filter)
首先字串會經過字元過濾器,他們的工作是在分詞前處理字串。字元過濾器能夠去除HTML標記,或者轉化為“&”為“and”等。
(2)分詞器( Tokenizer )
一個簡單的分詞器可以根據空格或逗號將單詞分開,表徵化為一個個獨立的詞(term)。
(3)標記過濾器 ( token filter )
最後,每個詞都通過所有表徵過濾(token filters),它可以修改詞(例如將"Quick"轉為小寫),去掉詞(例如停用詞像"a"、"and"``"the"等等),或者增加詞(例如同義詞像"jump"和"leap")
內建分析器
Elasticsearch還附帶了一些預裝的分析器,你可以直接使用它們。簡單介紹幾個:
- 標準分析器,Elasticsearch預設使用的分析器,它是分析各種語言文字最常用的選擇,根據 Unicode 聯盟 定義的 單詞邊界 劃分文字。刪除絕大部分標點。最後,將詞條小寫
- 簡單分析器,在任何不是字母的地方分隔文字,將詞條小寫
- 空格分析器,在空格的地方劃分文字
- 語言分析器,可以考慮指定語言的特點
3. Elasticsearch的對映
在傳統資料庫中,我們會為每個欄位指定儲存型別,例如:varchar,int,datetime等等,就是為了能更精確的儲存資料,防止資料型別格式混亂。
同樣,ES的索引欄位也需要為其指定型別,它就像資料庫中的 schema,這種在ES稱為對映(mapping)。
(1)動態對映和靜態對映
動態對映: 文件寫入es時,es可根據寫入內容的型別自動識別,生成mapping。主要的內容和型別的自動對映關係如下:
靜態對映: 手動為索引指定欄位型別
(2)自定義MAPPING
建立索引時,可以先定義好索引的結構,即mapping,包括每個欄位的型別,分析器,是否全文索引等。
1.型type
es中的欄位型別如下圖:
其中string中的text 和 keyword 的區別:
- text 用於索引全文值的欄位,例如電子郵件正文或產品說明。他們在被索引之前會通過分詞器將字串轉換為單個術語的列表。文字欄位不用於排序,很少用於聚合。
- keyword 用於索引結構化內容的欄位,例如電子郵件地址,主機名,狀態程式碼,標籤。它們通常用於過濾,排序,和聚合。keyword欄位只能按其確切值進行搜尋。
string型別的欄位,預設的,考慮到包含全文字,它們的值在索引前要經過分析器分析,並且在全文搜尋此欄位前要把查詢語句做分析處理。
對於string欄位,兩個最重要的對映引數是index和analyer。
2.index
index引數控制字串以何種方式被索引。它包含以下三個值當中的一個:
string型別欄位預設值是analyzed。如果我們想對映欄位為確切值,我們需要設定它為not_analyzed:
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}
其他簡單型別——long、double、date等等——也接受index引數,但相應的值只能是no和not_analyzed,它們的值不能被分析。
3.analyzer
對於analyzed型別的字串欄位,使用analyzer引數來指定哪一種分析器將在搜尋和索引的時候使用。預設的,Elasticsearch使用standard分析器,但是你可以通過指定一個內建的分析器來更改它,例如whitespace、simple或english。中文的可以使用ik分析器。
{
'value': {
'type': 'text',
'analyzer': 'ik_max_word',
'search_analyzer': 'ik_max_syn',
}
}
下面給出一個自定義mapping的示例
示例1:
"mappings": {
"doc": {
"properties": {
"uid": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "english",
"search_analyzer": "standard"
}
}
}
}
示例2:
mapping = {
"settings": {
"analysis": {
"analyzer": {
"ik_max_syn": {
"tokenizer": "ik_max_word",
"filter": ["synonym", "stopword"]
},
"ik_smart_syn": {
"tokenizer": "ik_smart",
"filter": ["synonym", "stopword"]
}
},
"filter": {
"synonym": {
"type": "synonym",
"synonyms_path": "analysis/synonym.txt",
"updateable": True
},
"stopword": {
"type": "stop",
"stopwords_path": "analysis/stopwords.txt",
"updateable": True
}
}
},
"similarity": {
"my_custom_similarity": {
"type": "BM25",
"k1": 1.2,
"b": 0.75,
"discount_overlaps": False
}
}
},
"mappings": {
'properties': {
'value': {
'type': 'text',
'analyzer': 'ik_max_word',
'search_analyzer': 'ik_max_syn',
},
'attr': {
'type': 'text',
'analyzer': 'ik_max_word',
'search_analyzer': 'ik_max_syn',
},
'node': {
"type": "keyword",
}
}
}
}
參考連結:https://blog.csdn.net/z69183787/article/details/78133883