Elasticsearch的type有什麼用處? 通過type元欄位實現了什麼功能? 底層如何使用? 有哪些註意事項/最佳實踐? 本篇文章對這些內容作一個簡單的探討. ...
目錄
1 type的作用
在Elasticsearch的索引(index)中, 通過標識元欄位_type
來區分不同的type, 所以我們可以把具有相同欄位(field)的文檔劃分到同一個type下.
==> 因而_type
也稱作映射類型, 即每個type都有各自的mapping.
但即使是類似的數據, 也有可能存在不同的field, 比如:
商品中有電子商品有電壓field;
服裝商品有洗滌方式field;
生鮮商品有營養成分field… 這些不同的field要如何處理呢?
==> 在之前的博文中有提到過: 同一index的不同type中, 同名的field的映射配置必須相同. 這是為什麼呢?
2 type的底層數據結構
Elasticsearch底層所使用的核心工具庫——Lucene中並沒有type的說法, 它在建立索引的時候, 會把所有field的值當做opaque bytes(不透明位元組)類型來處理:
在存儲document時, ES會將該document所屬的type作為一個
type
欄位進行存儲;在搜索document時, ES通過
_type
來進行過濾和篩選.
每個index中的所有type都是存儲在一起的, 因此:
在Elasticsearch 6.0之前: 同一個index的不同type中, 同名的field的映射配置(
_type
)必須相同.在Elasticsearch 6.0開始: 一個index中不能擁有多個type.
3 探究type的存儲結構
說明: 從Elasticsearch 6.0開始, 不允許在一個index中創建多個type ——只能創建一個, 否則將發生錯誤:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Rejecting mapping update to [website] as the final mapping would have more than 1 type: [manager, writer]"
}
],
"type": "illegal_argument_exception",
"reason": "Rejecting mapping update to [website] as the final mapping would have more than 1 type: [manager, writer]"
},
"status": 400
}
這裡演示所用的版本是6.6.10, 特此說明.
3.1 創建索引並配置映射
PUT website
{
"mappings": { // Elasticsearch 6.0之後的版本中, 只添加這一個type
"writer": {
"properties": {
"id": { "type": "long" },
"name": { "type": "text" },
"age": { "type": "integer" },
"sex": { "type": "text", "index": false }
}
},
"manager": { // 省去此type
"properties": {
"id": { "type": "long" },
"name": { "type": "text" },
"age": { "type": "integer" },
"sex": { "type": "text", "index": false },
"authorize": { "type": "text", "index": false}
}
}
}
}
3.2 添加數據
PUT website/writer/1
{
"id": 1001,
"name": "tester",
"age": 18,
"sex": "female"
}
// Elasticsearch 6.0之後的版本中, 不添加下述文檔:
PUT website/manager/1
{
"id": 1001,
"name": "shou feng",
"age": 20,
"sex": "male",
"authorize": "all"
}
3.3 查看存儲結構
// 搜索所有數據
GET website/_search
// 搜索結果如下:
{
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "website",
"_type" : "writer", // _type是writer
"_id" : "1",
"_score" : 1.0,
"_source" : {
"id" : 1001,
"name" : "tester",
"age" : 18,
"sex" : "female"
}
},
{
"_index": "website",
"_type": "manager", // _type為manager
"_id": "1",
"_score": 1,
"_source": {
"id": 1001,
"name": "shou feng",
"age": 20,
"sex": "male",
"authorize": "all"
}
}
]
}
}
4 關於type的最佳實踐
將結構類似的type存放在同一個index下 —— 這些type的大部分field應該是相同的.
如果將兩個field完全不同的type存入同一個index下, 在Lucene底層存儲時, 每個document中都將有一大部分field是空值, 這將導致嚴重的性能問題, 並且占用磁碟空間:
例如: 上述website/writer
的每個document中, 都有"authorize"欄位, 只是它們的值都為空.
—— 從這個角度出發, 大概就能猜出 ES限制一個index中只能有一個type 的原因了吧, 也就是更方便地組織文檔數據、節省磁碟空間