如何對Elasticsearch的索引數據進行增刪改查操作? 新增數據時是否指定id? 如何通過`_id`和`_source`元欄位查詢文檔, 全量修改和強制替換文檔的使用, 刪除文檔的原理...... 本篇文章作個比較詳細的說明~ ...
目錄
說在前面: 本文的所有演示, 都是基於Elasticsearch 6.6.10進行的, 不同的版本可能存在API發生修改、不支持的情況, 還請註意.
1 創建document
1.1 創建時手動指定id
(1) 適用情景:
從其他系統中導入數據到ES時, 會採取這種方式: 使用原有系統中數據已有的唯一標識, 作為ES中document的id.
而如果數據一生產出來就存儲到了ES中, 一般是不適合手動指定id的.
(2) 使用語法:
put index/type/id
(3) 使用示例:
PUT employee/developer/1
{
"name": "shoufeng",
"e_id": 5220
}
(4) 添加成功後的響應信息:
{
"_index" : "employee",
"_type" : "developer",
"_id" : "1", // 指定了id, 控制底層的_id元欄位
"_version" : 1, // 當前版本號, 基於此欄位進行併發控制
"result" : "created",
"_shards" : {
"total" : 2, // 參與創建的分片數, 包括Primary和Replica
"successful" : 1, // 成功創建索引的分片數量
"failed" : 0 // 創建索引失敗的分片數量
},
"_seq_no" : 0,
"_primary_term" : 1
}
1.2 創建時自動生成id
(1) 使用情景:
ES作為數據存儲伺服器, 應用程式中的數據直接對接到ES中, 這種場景適合自動生成id.
在多節點併發生成大量數據的場景下, 自動生成id更具安全性.
(2) 使用語法:
POST index/type
(3) 使用示例:
POST employee/developer
{
"name": "shoufeng",
"sex": "male",
"age": 20
}
(4) 添加成功後的響應結果:
{
"_index" : "employee",
"_type" : "developer",
"_id" : "vMxcFWoBfKUnm9s_Uxen", // 沒有指定id, 就會自動生成id, 長度為20個字元
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
官方文檔中指出:
Elasticsearch自動生成的id, 長度為20個字元, 是URL安全的, 它是Base64編碼的GUID字元串, 多節點(分散式系統)並行生成id時不會發生衝突.
2 查看document
2.1 根據id查詢文檔
查詢時可以不指定type, 即下述的developer, 而用_all代替.
// 查詢語法:
GET employee/developer/1
// 結果如下:
{
"_index" : "employee",
"_type" : "developer",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : { // 文檔的元數據
"name" : "shoufeng",
"e_id" : 5220
}
}
2.2 通過_source欄位控制查詢結果
(1) 只獲取指定id的文檔的_source
內容:
GET employee/developer/1/_source
// 結果是:
{
"name" : "shoufeng",
"e_id" : 5220
}
(2) 禁用指定id的文檔的_source
欄位:
GET employee/developer/1?_source=false
// 結果是:
{
"_index" : "employee",
"_type" : "developer",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true
}
(3) 過濾_source
中的某些field:
// _source_includes和_source_excludes可以匹配通配符*
GET employee/developer/1?_source_includes=name,age&_source_excludes=sex
GET employee/developer/_search?_source_includes=name,age&_source_excludes=sex
(4) 通過stored_fields
API過濾文檔中已存儲的欄位:
在Elasticsearch 6.0之後, 不再支持
fields
, 需要使用stored_fields
API替換.
GET employee/developer/1?stored_fields=name,age // 指定id
GET employee/developer/_search?stored_fields=name,age // 不指定id, 將查詢所有文檔
其他查詢操作, 將在後續的文章中專門記錄.
3 修改document
3.1 全量替換document
全量替換是基於指定文檔id的修改:
// 語法與創建語法相同:
PUT employee/developer/1
{
"name": "shoufeng001", // 修改姓名
"age": 20, // 添加年齡
"sex": "male", // 添加性別
"e_id": 5220
}
操作過程說明:
① 如果指定的document id不存在, 就是創建操作;
② 如果指定的document id已經存在, 就是全量替換操作 —— 替換舊文檔的JSON串內容;
③ Lucene中倒排索引一旦被創建就是不可變的, 要修改文檔內容, 可以採取全量替換的方式 —— 對文檔重新建立索引, 替換舊文檔的所有內容;
④ ES會將舊文檔標記為deleted, 然後根據我們提交的請求創建一個新文檔, 當標記為deleted的文檔數達到一定量時, ES會在自動刪除這些舊文檔.
3.2 強制創建document
(1) 存在這樣的場景:
我們不知道索引中是否已經存在某個文檔 —— 可能有其他用戶在併發添加文檔;
為了防止創建操作被執行為全量替換操作, 從而導致數據的丟失, 我們可以使用強制創建的方式, 來避免這種失誤.
(2) 強制創建示例:
PUT employee/developer/1?op_type=create
{
"name": "shoufeng",
"age": 20
}
// 或者使用:
PUT employee/developer/1/_create
{
"name": "shoufeng",
"age": 20
}
// 響應結果中出現衝突:
{
"error": {
"root_cause": [
{ // 由於文檔已經存在, 發生版本衝突, 導致創建失敗
"type": "version_conflict_engine_exception",
"reason": "[developer][1]: version conflict, document already exists (current version [2])",
"index_uuid": "OYu6J2x_S2S5v-R74aq6NQ",
"shard": "3",
"index": "employee"
}
],
"type": "version_conflict_engine_exception",
"reason": "[developer][1]: version conflict, document already exists (current version [2])",
"index_uuid": "OYu6J2x_S2S5v-R74aq6NQ",
"shard": "3",
"index": "employee"
},
"status": 409
}
出現衝突的原因:
① Elasticsearch通過樂觀鎖控制每個文檔的
_version
信息, 強制創建語法會對當前操作的文檔的_version
信息進行初始化;② 添加索引時, 發現已經存在對應id的文檔, 而且其版本號與正在強制創建的文檔的版本信息不匹配, 所以報錯.
出現衝突後, 我們就能知道索引中已存在該文檔了, 就可以根據自己的應用需求, 採取更改id後重新添加, 或者更改已有的文檔等操作.
4 刪除document
(1) 刪除語法:
DELETE index/type/id
(2) 刪除示例:
DELETE employee/developer/1
// 再次查看id為1的文檔, 發現"found": false
(3) Elasticsearch刪除文檔採取的是懶刪除機制:
不會立即物理刪除, 而是將其標記為deleted, 當被刪除的文檔數量達到一定級別後, ES會在後臺自動刪除這些文檔.
版權聲明
作者: 馬瘦風
出處: 博客園 馬瘦風的博客
您的支持是對博主的極大鼓勵, 感謝您的閱讀.
本文版權歸博主所有, 歡迎轉載, 但請保留此段聲明, 併在文章頁面明顯位置給出原文鏈接, 否則博主保留追究相關人員法律責任的權利.