ElasticSearch - 批量操作 bulk

  • bulk允許在一個請求中進行多個操作(create、index、update、delete),也就是可以在一次請求裡做很多事情

    • 也由於這個關係,因此bulk的請求體和其他請求的格式會有點不同

  • bulk的請求模板

    • 分成action、metadata和doc三部份

      • action : 必須是以下4種選項之一

        • index(最常用) : 如果文檔不存在就創建他,如果文檔存在就更新他

        • create : 如果文檔不存在就創建他,但如果文檔存在就返回錯誤

          • 使用時一定要在metadata設置_id值,他才能去判斷這個文檔是否存在

        • update : 更新一個文檔,如果文檔不存在就返回錯誤

          • 使用時也要給_id值,且後面文檔的格式和其他人不一樣

        • delete : 刪除一個文檔,如果要刪除的文檔id不存在,就返回錯誤

          • 使用時也必須在metadata中設置文檔_id,且後面不能帶一個doc,因爲沒意義,他是用_id去刪除文檔的

      • metadata : 設置這個文檔的metadata,像是_id_index_type...

      • doc : 就是一般的文檔格式

      POST 127.0.0.1/mytest/doc/_bulk
      { action : { metadata } }
      { doc }
      { action : { metadata } }
      { doc }
      ....
  • 具體實例

    • bulk請求

      POST 127.0.0.1/mytest/doc/_bulk
      //創建一筆數據
      { "create" : { "_id": 1 } }
      { "color": "create black" }
      //創建一筆數據,因爲id=1的文檔已經存在,所以會創建失敗
      { "create" : { "_id": 1 } }
      { "color": "create black2" }
      //索引一筆數據
      { "index" : { "_id": 2 } } 
      { "color": "index red" }
      //索引一筆數據,但是index可以創建也可以更新,所以執行成功
      { "index" : { "_id": 2 } } 
      { "color": "index red2" }
      //索引一筆數據,不一定要設置id(index又能創建又能更新又不用設id,超好用)
      { "index": {} } 
      { "color": "index blue" } 
      //刪除一筆文檔,注意delete後面不接一個doc
      { "delete" : { "_id": "2" } } 
      //找不到此id的文檔,刪除失敗
      { "delete" : { "_id": "2" } } 
      //更新一筆文檔,注意doc格式不太一樣
      { "update" : { "_id": 1 } } 
      { "doc": { "color": "update green"} }
      //更新一筆文檔,但因爲此id的文檔不存在,所以更新失敗
      { "update" : { "_id": 100 } } 
      { "doc": { "color": "update green2"} }
  • bulk的返回結果

    • 因爲在bulk中,每個action的執行結果都是獨立的,所以有幾個action,就會有幾個返回結果,返回結果如下

      • 最上面會有一個errors,表示這一次bulk請求中,是否有action出錯了

        • 因此寫代碼時可以先檢查errors這個值,如果是false,表示這次bulk請求全部通過,就不用再一一去檢查是否有action出錯,但如果是true,則必須去items一個一個檢查到底是哪個action出錯了

      • items是一個數組,裡面則放著每個action對應的結果,上面的請求執行了9個action,所以返回結果的items就會有9個

        • 返回結果會依照action的順序排好,因此items的第一個結果就是請求時第一個action的執行結果

      {
          "took": 22,
          "errors": true,
          "items": [
              {
                  "create": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "1",
                      "status": 201
                  }
              },
              {
                  "create": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "1",
                      "status": 409,
                      "error": {
                          "type": "version_conflict_engine_exception",
                          "reason": "[doc][1]: version conflict, document already exists (current version [1])",
                          "index_uuid": "hc_2I5efRMK3_RUC0HJGew",
                          "shard": "3",
                          "index": "mytest"
                      }
                  }
              },
              {
                  "index": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "2",
                      "status": 201
                  }
              },
              {
                  "index": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "2",
                      "status": 200
                  }
              }
              ... 5 RESULTS REMOVED ...
          ]
      }
  • 使用bulk要注意的地方

    • 如果使用127.0.0.1/_bulk,那麼就是在整個ES的範圍中插入數據,因此在metadata中要指定插入的index和type,優點是可以一次插入多筆數據到不同的索引

      • 而如果使用127.0.0.1/mytest/doc/_bulk,就不用在metadata再次指定要插入的index和type,可以想像成是_bulk API幫我們自動填好了metadata的_index_type,很方便

    • 還有因爲bulk和其他請求的格式不同,或是說基本上他已經不是正常的json格式了,所以在使用bulk時,HTTP header要使用application/x-ndjson

      • 而且每一行的結尾,都要使用\n,如果是一般在postman寫請求不會有問題,但是如果是使用curl來發送請求,就要使用--data-binary,纔會使每一句的結尾都是\n

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章