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 

 


免責聲明!

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



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