一、確切值(Exact values) vs 全文文本(Full text)
Elasticsearch中的數據可以大致分爲兩種類型
- 確切值,確切值是確定的,正如它的名字一樣。比如一個date或用戶ID,需要精確匹配,對於2019-11-8,只輸入2019-11是不能被檢索出來,必須精確匹配
- 全文文本,Elasticsearch會對文本分析(analyzes),然後使用結果建立一個倒排索引,比如,可以支持模糊匹配,忽略大小寫,近義詞匹配
二、Elasticsearch分析器
分析器需要完成以下分析過程:
- 表徵化一個文本塊爲適用於倒排索引單獨的詞(term)
- 然後標準化這些詞爲標準形式,提高他們的“可搜索性”
ES分析器組成:
- 字符過濾器
首先字符串經過過濾器(character filter),他們的工作是在表徵化前處理字符串。字符過濾器能夠去除HTML標記,或者轉化爲“&”爲“and” - 分詞器( Tokenizers ) 可以根據空格或逗號將單詞分開
分詞器(tokenizer)被表徵化爲獨立的詞。一個簡單的分詞器(tokenizer)可以根據空格或逗號將單詞分開(注:這個在中文中不適用) - 標記過濾器 ( token filters )
每個詞都通過所有表徵過濾(token filters),可以修改詞(例如將“Quick”轉爲小寫),去掉詞(例如停用詞像“a”、“and”、“the”等等),或者增加詞(例如同義詞像“a”、“and”、“the”等等)或者增加詞(例如同義詞像“jump”和“leap”)
內置分析器
- 標準分析器,Elasticsearch默認使用的分析器,它是分析各種語言文本最常用的選擇,根據 Unicode 聯盟 定義的 單詞邊界 劃分文本。刪除絕大部分標點。最後,將詞條小寫
- 簡單分析器,在任何不是字母的地方分隔文本,將詞條小寫
- 空格分析器,在空格的地方劃分文本
- 語言分析器,可以考慮指定語言的特點
什麼時候使用分析器?
當我們索引一個文檔,它的全文域被分析成詞條以用來創建倒排索引。 但是,當我們在全文域搜索 的時候,我們需要將查詢字符串通過 相同的分析過程 ,以保證我們搜索的詞條格式與索引中的詞條格式一致
- 當你查詢一個全文域時, 會對查詢字符串應用相同的分析器,以產生正確的搜索詞條列表。
- 當你查詢一個精確值域時,不會分析查詢字符串,而是搜索你指定的精確值
三、映射介紹
數據庫中的表,我們一般在DDL語句中爲每個字段指定存儲類型,例如:varchar,int,datetime等等,目的很明確,就是更精確的存儲數據,防止數據類型格式混亂
類比數據庫,ES的索引字段也需要爲其指定類型,它就像數據庫中的 schema,這種在ES稱爲映射(mapping)
映射是定義一個文檔及其包含的字段如何存儲和索引的過程,可以從以下幾個方面理解:
- 將哪些字符串字段視爲全文字段
- 哪些字段包含數字,日期或地理位置
- 日期值的格式
- 自定義規則以控制動態添加字段的映射
動態映射: 文檔寫入es時,es可根據寫入內容的類型自動識別,生成mapping
靜態映射: 手動爲索引指定字段類型
四、字段類型
JSON格式的數據 | 自動推測字段類型 |
---|---|
null | 沒有字段被添加 |
true or false | boolean |
浮點類型數字 | float類型 |
數字 | long類型 |
JSON對象 | object類型 |
數組 | 由數組中第一個非空值決定 |
string | 有可能是date類型(開啓日期檢測)、double或long類型、text類型、keyword類型 |
text 和 keyword 的區別:
- text 用於索引全文值的字段,例如電子郵件正文或產品說明。這些字段是analyzed,它們通過分詞器傳遞 ,以在被索引之前將字符串轉換爲單個術語的列表。分析過程允許Elasticsearch搜索單個單詞中 每個完整的文本字段。文本字段不用於排序,很少用於聚合
- keyword 用於索引結構化內容的字段,例如電子郵件地址,主機名,狀態代碼,郵政編碼或標籤。它們通常用於過濾,排序,和聚合。keyword字段只能按其確切值進行搜索。如果您需要索引電子郵件正文或產品說明等全文內容,則可能應該使用text字段
有時候單純的一個字段類型滿足不了我們複雜的需求,爲了不同的目的,以不同的方式索引同一個字段通常很有用,例如,對於字符串字段,我們既可以將它映射爲text類型用於全文搜索,亦可以將它映射爲keyword類型用於排序或聚合,或者,還可以使用標準分詞器、英語分詞器和其他語言分詞器索引文本字段
前面說過,當 Elasticsearch 遇到文檔中以前 未遇到的字段,它用 dynamic mapping 來確定字段的數據類型並自動把新的字段添加到類型映射。
如果不希望這樣,可以使用dynamic參數設置
- true,動態添加新的字段
- false,忽略新的字段
- strict,如果遇到新字段拋出異常
配置參數 dynamic 可以用在根 object 或任何 object 類型的字段上。你可以將 dynamic 的默認值設置爲 strict , 而只在指定的內部對象中開啓它, 例如:
PUT /my_index
{
"mappings": {
"my_type": {
"dynamic": "strict",
"properties": {
"title": { "type": "string"},
"stash": {
"type": "object",
"dynamic": true
}
}
}
}
}
- 如果遇到新字段,對象 my_type 就會拋出異常
- 內部對象 stash 遇到新字段就會動態創建新字段
參考
Elasticsearch權威指南