Mapping (映射)類似關係型資料庫中的表的結構定義。我們將數據以 JSON 格式存入到 ElasticSearch 中後,在搜索引擎中 JSON 欄位映射對應的類型,這時需要 mapping 來定義內容的類型。 ...
本文案例操作,建議先閱讀我之前的文章《ElasticSearch之安裝及基本操作API》
Mapping (映射)類似關係型資料庫中的表的結構定義。我們將數據以 JSON 格式存入到 ElasticSearch 中後,在搜索引擎中 JSON 欄位映射對應的類型,這時需要 mapping 來定義內容的類型。
欄位類型
JSON 數據類型映射到 ElasticSearch 定義的類型,常用的簡單類型有:
JSON類型 | ElasticSearch 類型 |
---|---|
文本類型 | Text/Keyword |
整數類型 | long/integer |
浮點類型 | float/double |
時間類型 | date |
布爾值 | boolean |
數組 | Text/Keyword |
上面要註意的是時間類型,JSON 中並沒有時間類型,這裡主要指時間格式數據的類型。
定義映射
在關係型資料庫中,存儲數據之前,我們會先創建表結構,給欄位指定一個存在的類型。同樣 ElasticSearch 在進行數據存儲前,也可以先定義好存儲數據的 Mapping 結構。
先定義一個簡單的 person Mapping:
上圖中就是一個 Mapping 的定義,如果是在 ElasticSearch7 之前,mappings 里還有 _type 屬性。
動態映射
當沒有事先定義好 Mapping,添加數據時,ElasticSearch 會自動根據欄位進行換算出對應的類型,但是換算出來的類型並不一定是我們想要的欄位類型,還是需要人為的干預進行修改成想要的 Mapping。
更新映射
使用 dynamic 控制映射是否可以被更新。
dynamic-true
設置 dynamic 為true
是預設 dynamic 的預設值,新增欄位數據可以寫入,同時也可以被索引,Mapping 結構也會被更新。
添加數據,同時多添加一個沒被定義的 gender
欄位。
# 向 person 中添加數據
PUT person/_doc/1
{
"uId": 1,
"name": "ytao",
"age": 18,
"address": "廣東省珠海市",
"birthday": "2020-01-15T12:00:00Z",
"money": 108.2,
"isStrong": true,
"gender": "男" # Mapping 中未定義的欄位
}
添加成功,搜索 gender
欄位:
查看 Mapping 結構:
新添加的欄位值,在添加過程中 Mapping 已自動添加欄位。
dynamic-false
設置 dynamic 為false
時,新增欄位數據可以寫入,不可以被索引,Mapping 結構會被更新。
同樣先將 dynamic 設置為 false,然後向裡面添加數據,其他步驟和上面 true 操作一樣。定義 Mapping,添加數據。
搜索 gender
欄位:
此時新增欄位數據無法被索引,但數據可以寫入。
Mappnig 也不會添加新增的欄位:
dynamic-strict
設置 dynamic 為strict
時,從字面上意思也可以看出,對於動態映射是較嚴格的,新增欄位數據不可以寫入,不可以被索引,Mapping 結構不會被更新。只能按照定義好的 Mapping 結構添加數據。
在添加新欄位數據時,就馬上會拋出異常:
自動識別日期類型
上文中,當 dynamic 設置為 true 時,添加新欄位數據自動識別類型更新 Mapping,如果是日期類型的話,我們是可以指定識別的類型。
指定 person 的 dynamic_date_formats 格式:
PUT person/_mapping
{
"dynamic_date_formats": ["yyyy/MM/dd"]
}
這裡是可以指定多個時間格式。
向 person 添加新數據,分別是 today 和 firstDate:
PUT person/_doc/2
{
"today": "2020-01-15",
"firstDate": "2020/01/15"
}
添加新欄位數據後的 Mapping:
由於上面我們指定了時間格式為 yyyy/MM/dd
時是可以識別為時間格式,所以 today 欄位的值為 yyyy-MM-dd
格式無法識別為時間類型,判為 text 類型。
多欄位
Mapping 中可以定義 fields 多欄位屬性,以滿足不同場景下的實現。比如 address
定義為 text
類型,fields 裡面又有定義 keyword
類型,這裡主要是區分兩個不同不同使用場景。
text
會建立分詞倒排索引,用於全文檢索。keyword
不會建立分詞倒排索引,用於排序和聚合。
添加數據:
# 向 person 中添加數據
PUT person/_doc/1
{
"uId": 1,
"name": "ytao",
"age": 18,
"address": "廣東省珠海市",
"birthday": "2020-01-15T12:00:00Z",
"money": 108.2,
"isStrong": true
}
查詢address
數據。
查詢address.keyword
數據。
通過keyword
檢索時,由於不會建立分詞索引,並沒有獲取到數據。
控制索引
在欄位中使用 index 指定當前欄位索引是否能被搜索到。指定類型為 boolean 類型,false 為不可搜索到,true 為可以搜索到。
先刪除之前的 Mapping:
DELETE person
創建 Mapping,設置name
屬性的 index
為 false。
再次添加上面的數據後搜索name
欄位:
欄位 index 設置 false 後,由於沒有被索引,所以搜索無法獲取到索引。
空值處理
現在向 ElasticSearch 中添加一條 address 為空的數據:
PUT person/_doc/2
{
"uId": 2,
"name": "Jack",
"age": 22,
"address": null,
"birthday": "2020-01-15T12:00:00Z",
"money": 68.7,
"isStrong": true
}
搜索 address.keyword 為空的數據:
搜索返回異常,預設是不被允許搜索 NUll。
這是需要在 Mapping 指定 null_value 屬性,並且不能在text
類型中聲明。
搜索 address.keyword 為空的數據:
設置 "null_value": "NULL"
後,空值可以處理搜索。
聚合多個欄位
聚合多個欄位放到一個索引中,使用 copy_to 進行聚合。例如我們在多欄位查詢中,這是不需要對每個欄位進行過濾篩選,只需對聚合欄位即可。
在使用 copy_to 時,是通過指定聚合的名稱實現。
實際上,copy_to 不使用數組格式添加名稱,也會自動轉換成數據格式。
添加兩條數據,待校驗搜索:
# 向 person 中添加數據
PUT person/_doc/1
{
"uId": 1,
"name": "ytao",
"age": 18,
"address": "廣東省珠海市",
"birthday": "2020-01-15T12:00:00Z",
"money": 108.2,
"isStrong": true
}
PUT person/_doc/2
{
"uId": 2,
"name": "楊廣東",
"age": 22,
"address": null,
"birthday": "2020-01-15T12:00:00Z",
"money": 68.7,
"isStrong": true
}
查詢 full_name
的值,會返回 name 和 address 相關的值的對象。
從上面返回結果看到,_source 中的欄位沒有增加相應的 copy_to 欄位名,所以 copy_to 只會拷貝欄位內容至索引,並不會改變包含的欄位。
總結
通過本文對創建 Mapping 文件的常用並且實用的操作介紹,也基本能掌握這些日常的使用。瞭解 Mapping 的功能操作,相信對存儲時的設計也有一定幫助。
個人博客: https://ytao.top
關註公眾號 【ytao】,更多原創好文