1. 程式人生 > >elasticsearch(3) 資料操作-更新

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