elasticsearch(3) 資料操作-更新
一 更新整個文件
更新整個文件的方法和存放資料的方式是相同的,通過PUT 127.0.0.1/test/test/1 我們可以把test/test/1下的文件更新為新的文件
例:
PUT 127.0.0.1:9200/test/test/1
引數
{ "newdata":"yes" }
響應
{ "_index": "test", "_type": "test", "_id": "1", "_version": 2, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 1, "_primary_term": 1 }
可以看到響應的引數裡_version已經變為了2,並且result為updated 說明此操作為更新操作
二 文件區域性更新
如果不想講原有文件完全更新,只想更新部分文件,可以使用ES的_update api 引數是一個區域性文件引數doc,它會合併到現有文件中,存在的欄位被覆蓋,有點類似map的putAll操作
示例
POST 127.0.0.1;9200/test/test/1/_update
引數
{ "doc":{"newdata":"no", "author":"wuzhe" } }
響應
{ "_index": "test", "_type": "test", "_id": "1", "_version": 3, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 2, "_primary_term": 1 }
三 刪除文件
想要刪除文件,可以使用DELETE 請求方式
示例:
DELETE 127.0.0.1:9200/test/test/1
響應
{ "_index": "test", "_type": "test", "_id": "1", "_version": 4, "result": "deleted", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 3, "_primary_term": 1 }
如果刪除成功,那麼狀態碼為200 ,且result 為deleted, 我們可以看到響應中的_version由3變為了4,也就是版本號發生了變化,這是因為對於ES來說,刪除文件並不是把它從硬碟中物理刪除,而是將其標記為已刪除,實現邏輯上的刪除
那如果沒有刪除成功,響應會是什麼樣的呢?
我們嘗試刪除一個不存在的文件
DELETE 1270.0.01:9200/test/test/100
響應
{ "_index": "test", "_type": "test", "_id": "100", "_version": 1, "result": "not_found", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
這時候 響應狀態碼變為了404,並且result變為了not_found
四 建立文件
之前說到的完整文件更新和新建文件的操作是完全一樣的,那我如何確定這次操作一定是建立操作呢,畢竟絕大多數情況,我們並不想一不小心覆蓋了已有文件的資料
一種方案是,採用ES自動生成的ID,這樣可以保證每次插入操作都是建立操作
那如果我一定要使用自定義的ID呢?
可以通過使用op_type這個引數
示例
PUT 127.0.0.1:9200/test/test/6?op_type=create
請求引數為文件內容
{ "test":"test", "author":"wuzhe" }
響應
{ "_index": "test", "_type": "test", "_id": "6", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 2, "_primary_term": 1 }
可以看到這裡文件新建成功了,result為created並且version為1
如果我們再次執行相同的操作,即對已有資料進行建立
響應
{ "error": { "root_cause": [ { "type": "version_conflict_engine_exception", "reason": "[test][6]: version conflict, document already exists (current version [1])", "index_uuid": "7i4nU37hQJWCRUm1Hop0Gw", "shard": "2", "index": "test" } ], "type": "version_conflict_engine_exception", "reason": "[test][6]: version conflict, document already exists (current version [1])", "index_uuid": "7i4nU37hQJWCRUm1Hop0Gw", "shard": "2", "index": "test" }, "status": 409 }
可以看到這時候的響應碼為409,說明版本號衝突了,無法建立成功。
五 版本控制
在併發場景下,ES使用樂觀併發控制的方式,ES保證所有的文件的_version都能被正常排序,當一箇舊版本的文件出現在新版本之後,那麼它會被ES簡單的忽略
1、使用指定版本號修改文件
在修改文件的時候使用version引數
示例:
PUT 127.0.0.1:9200/test/test/6?version=1 (只有在文件版本為1的情況下更新成功)
引數:
{ "test":"test1", "author":"wuzhe" }
響應
{ "_index": "test", "_type": "test", "_id": "6", "_version": 2, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 3, "_primary_term": 1 }
可以看到這時候更新成功了,因為/test/test/6 的版本之前為1,現在更新為了2,。
我們再嘗試一次請求,這時候的響應變成了
{ "error": { "root_cause": [ { "type": "version_conflict_engine_exception", "reason": "[test][6]: version conflict, current version [2] is different than the one provided [1]", "index_uuid": "7i4nU37hQJWCRUm1Hop0Gw", "shard": "2", "index": "test" } ], "type": "version_conflict_engine_exception", "reason": "[test][6]: version conflict, current version [2] is different than the one provided [1]", "index_uuid": "7i4nU37hQJWCRUm1Hop0Gw", "shard": "2", "index": "test" }, "status": 409 }
說明更新時遇到了版本號衝突,這時候響應狀態碼為409
2、使用外部版本控制系統
一種常見的結構是使用一些其他的資料庫做為主資料庫,然後使用Elasticsearch搜尋資料,這意味著所有主資料庫發生變化,就要將其拷貝到Elasticsearch中。如果有多個程序負責這些資料的同步,就會遇到上面提到的併發問題。
如果主資料庫有版本欄位,或一些類似於timestamp
等可以用於版本控制的欄位 你就可以在Elasticsearch的查詢字串後面新增version_type=external
來使用這些版本號。版本號必須是整數,且值大於零小於java正的Long型最大值
外部版本號與之前說的內部版本號在處理的時候有些不同。它不再檢查_version
是否與請求中指定的一致,而是檢查是否小於指定的版本。如果請求成功,外部版本號就會被儲存到_version
中。
示例:
PUT 127.0.0.1:9200/test/test/6?version=10&version_type=external
請求
{ "test":"test10", "author":"wuzhe" }
響應
{ "_index": "test", "_type": "test", "_id": "6", "_version": 10, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 4, "_primary_term": 1 }
可以看到之前test/test/6的版本號為2, 現在已經被更新為了10