ES 16 - 增刪改查Elasticsearch中的索引數據 (CRUD)


說在前面: 本文的所有演示, 都是基於Elasticsearch 6.6.0進行的, 不同的版本可能存在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_fieldsAPI替換.

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會在后台自動刪除這些文檔.

版權聲明

作者: 馬瘦風(https://healchow.com)

出處: 博客園 馬瘦風的博客(https://www.cnblogs.com/shoufeng)

感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜

本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文鏈接], 否則博主保留追究相關人員法律責任的權利.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM