Elastic學習之旅(4)ES文檔CRUD操作

大家好,我是Edison。

上一篇:ES必備基礎概念一覽

ES文檔CRUD介紹

和MongoDB一樣,文檔的CRUD是我們學習ES的必備操作,下圖展示了ES文檔的CRUD概要:

從上圖可以知道,ES文檔除了CRUD外,還多了一個Index操作,它的功能Create類似,但又有點不同:

  • Create - 如果ID存在,則會失敗;否則新增成功;

  • Index - 如果ID存在,會先刪除現有文檔再創建新的,版本號會增加;否則,直接新增成功;

因此,我們可以說Index的功能或許可以叫 AddOrReplace。

Create文檔

Create文檔支持生成文檔ID 和 指定文檔ID 兩種方式:

自動生成ID

通過調用 post {index}/_doc,系統會自動生成文檔ID。

由上圖可知,系統自動生成了一個ID。

指定ID

通過調用 put {index}/_create/1,系統會指定新生成文檔ID爲1。但如果指定ID已經存在,操作則失敗。

由上圖可知,我們傳了一個指定ID=1。但是,如果我們再次執行這條語句會如何?

再次執行會報錯,因爲ES檢測到這個數據版本已經存在了。

Get文檔

通過get {index}/_doc/{id}即可快速查詢一個文檔數據,如果沒有找到,則返回HTTP 404。

在返回的文檔中,文檔的真正內容在_source字段裏面。

在返回的文檔中,還包含了文檔元信息:

  • _index / _type 

  • 版本信息,同一個ID的文檔,即使被刪除,version號也會不斷增加 

  • _source中默認包含了文檔的所有原始信息

Index文檔

剛剛提到,Index 和 Create 不一樣的地方在於:

  • 如果文檔不存在,就索引新的文檔。

  • 如果文檔已存在,舊文檔會先被刪除,新文檔會被索引,同時版本號+1。

因此,Index操作更像是我們所說的“AddOrReplace”。

通過put {index}/_doc/{id}即可完成Index操作,這裏我們以剛剛get的示例爲基礎,修改id=1的user的username,由於id=1記錄已存在,會先刪除舊文檔,再索引新文檔:

從上圖可以看到,當Index操作完成後,version號從1變爲了2。

這時如果我們再查詢一個id=1的文檔,會發現已被新文檔覆蓋了,只有一個user字段了。

Update文檔

Update方法就是真正的數據更新,它不會刪除原來的文檔。

通過post {index}/_update/{id}即可實現Update操作。

這時我們再次get一下,得到的結果:

可以看到,新增的數據已經加入了文檔內容中,並且version又增加了一位。

Delete文檔

可以通過 delete {index}/_doc/{id}來完成文檔的刪除操作。

可以看到,返回的結果狀態顯示爲deleted,則表示刪除成功。

這時如果再次查詢這個文檔,就會顯示找不到了:

批量操作API(Bulk API)

ES提供了一個Bulk API,支持在一次API調用中,對不同的索引進行不同類型(如Index、Create、Update、Delete)的操作,可以有效減少網絡連接所產生的開銷。

POST _bulk
{ "index": { "_index":"test", "_id":"1" } }
{ "filed1": "value1" }
{ "delete": { "_index":"test", "_id":"2" } }
{ "create": { "_index":"test2", "_id":"3"  } }
{ "filed1": "value3" }
{ "update": { "_index":"test", "_id":"1" } }
{ "doc": { "field2":"value2" } }

其返回結果包含了每一條操作執行的結果。

{
  "took" : 854,
  "errors" : false,
  "items" : [
    {
      "index" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "delete" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "2",
        "_version" : 1,
        "result" : "not_found",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 404
      }
    },
    {
      "create" : {
        "_index" : "test2",
        "_type" : "_doc",
        "_id" : "3",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "update" : {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 2,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 2,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}

需要注意的是:操作中單條操作失敗,並不影響其他操作。此外,單次批量操作,數據量不宜過大,以免引發性能問題。

批量讀取(mget)

和批量操作類似,ES提供了一個mget實現批量讀取,可以減少網絡連接產生的開銷,提高讀取的性能。

通過 get /_mget即可完成:

GET /_mget
{
  "docs":[
    {
      "_index":"users",
      "_id":1
    },
    {
      "_index":"users",
      "_id":2
    }
  ]
}

返回結果包含了多個數據:

{
  "docs" : [
    {
      "_index" : "users",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "_seq_no" : 5,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "user" : "Andy",
        "postDate" : "2024-01-20T15:00:00",
        "message" : "Trying to use ElasticSearch"
      }
    },
    {
      "_index" : "users",
      "_type" : "_doc",
      "_id" : "2",
      "_version" : 1,
      "_seq_no" : 6,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "user" : "Wings",
        "postDate" : "2024-01-20T15:00:00",
        "message" : "Trying to use EFK"
      }
    }
  ]
}

批量查詢(msearch)

和批量讀取類似,ES提供了一個msearch實現批量查詢,通過post {index}/_msearch即可完成:

POST users/_msearch
{}
{"query":{"match_all":{}},"size":3}
{"index":"movies"}
{"query":{"match_all":{}},"size":2}

例如上面這個批量查詢,它從users中查詢了3個數據 還從 movices中查詢了2個數據出來:

{
  "took" : 7,
  "responses" : [
    {
      "took" : 7,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "users",
            "_type" : "_doc",
            "_id" : "5-46K40BoVgALGyCI5vL",
            "_score" : 1.0,
            "_source" : {
              "user" : "Edison",
              "postDate" : "2024-01-20T14:00:00",
              "message" : "Trying to use Kibana"
            }
          },
          {
            "_index" : "users",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "user" : "Andy",
              "postDate" : "2024-01-20T15:00:00",
              "message" : "Trying to use ElasticSearch"
            }
          },
          {
            "_index" : "users",
            "_type" : "_doc",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "user" : "Wings",
              "postDate" : "2024-01-20T15:00:00",
              "message" : "Trying to use EFK"
            }
          }
        ]
      },
      "status" : 200
    },
    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 9743,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "movies",
            "_type" : "_doc",
            "_id" : "3687",
            "_score" : 1.0,
            "_source" : {
              "year" : 0,
              "@version" : "1",
              "title" : "Light Years",
              "id" : "3687",
              "genre" : [
                "Adventure",
                "Animation",
                "Fantasy",
                "Sci-Fi"
              ]
            }
          },
          {
            "_index" : "movies",
            "_type" : "_doc",
            "_id" : "3688",
            "_score" : 1.0,
            "_source" : {
              "year" : 1982,
              "@version" : "1",
              "title" : "Porky's",
              "id" : "3688",
              "genre" : [
                "Comedy"
              ]
            }
          }
        ]
      },
      "status" : 200
    }
  ]
}

常見錯誤返回

ES的一些常見錯誤返回的表格,供我們學習參考。

小結

本篇,我們瞭解了ElasticSearch的一些必備基礎概念,如索引、文檔、集羣、節點、分片與副本等。有了這些基本概念,我們可以知道ElasticSearch和關係型數據庫的差別。

參考資料

極客時間,阮一鳴,《ElasticSearch核心技術與實戰

 

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