《從0開始學Elasticsearch》—document的單/批量crud

內容目錄

1.新建文檔2.查詢文檔3.修改文檔4.刪除文檔css

1.新建文檔

1). 語法1,手動指定document 的id:java

PUT /index_name/type_name/id
{
    "Json format data"
}
複製代碼

舉例:插入一條商品信息python

PUT /goods/books/1
{
  "name":"effective java",
  "purchasePrice":7800,
  "salesPrice":12000,
  "currencyUnit":"cent",
  "desc":"Joshua Bloch",
  "onlineStock":999
}
複製代碼

運行結果:mysql

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
複製代碼

能夠看到,商品已經插入成功,ES自動爲咱們建立了index和type,若想禁止ES自動建立,咱們能夠修改config/elasticsearch.yml文件。nginx

其中,輸出中的 _index 元數據代表document 所在的index,index名稱必須爲小寫字母,能夠包含下劃線、中劃線,但只能以小寫字母開頭。在ES 6.6版本中,index的概念相似於mysql中的table,而非database。c++

同理,_type元數據代表document 所在的type,type是對document 的一個邏輯分類。sql

_id元數據代表document 的id,能夠在建立document 時手動指定,也能夠由ES自動生成,若由ES自動生成,咱們應該用POST方法而非PUT方法,即下文的語法2。json

_version代表當前document 的版本,_version元數據很是有效,從結果中咱們能夠看到,第一次建立document ,_version的值爲1,其實之後咱們對該document 進行修改或刪除操做,_version的值都會加1,後續操做時,咱們能夠留意觀察一下;另外,_version還被ES用於解決併發衝突的問題,當有併發請求時,ES內部實現了基於_version的樂觀鎖併發控制:當要修改document 數據時,帶上數據的version版本號,只有version版本號相同時,ES纔會更新數據,不然你須要先獲取一下最新的數據,而後再帶上最新的version去更新數據。bash

2). 語法2,document 的id由ES自動生成:併發

POST /index_name/type_name
{
    "Json format data"
}
複製代碼

舉例:

POST /goods/books
{
  "name":"effective c++",
  "purchasePrice":4500,
  "salesPrice":5900,
  "currencyUnit":"cent",
  "desc":"Scott Meyers",
  "onlineStock":888
}
複製代碼

運行結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "bEYCL2kB8EI9vT4zSMMW",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
複製代碼

能夠看到ES爲咱們自動生成了id,長度20字符,是一種GUID,不會重複。

3). 語法3,利用 bulk API 的create 操做批量建立document :
bulk API 能夠總結爲:

{ action: { metadata }}\n
request body        }\n
{ action: { metadata }}\n
request body        }\n
......
複製代碼

批量建立document 則爲:

POST /_bulk
{"create":{"_index":"index_name1","_type":"type_name1","_id":"id1"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"...}
{"create":{"_index":"index_name2","_type":"type_name2","_id":"id2"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"...}
...
複製代碼

若批量建立的document 在同一個index,則上述寫法能夠簡寫爲

POST /index_name/_bulk
{"create":{"_type":"type_name1","_id":"id1"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"...}
{"create":{"_type":"type_name2","_id":"id2"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"...}
...
複製代碼

若批量建立的document 既在同一個index,又在同一個type中,則能夠繼續簡寫爲

POST /index_name/type_name/_bulk
{"create":{"_id":"id1"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"}
{"create":{"_id":"id2"}}
{"field1":"field_data1","field2":"field_data2","field3":"field_data3"}
...
複製代碼

例如,批量建立ID爲 8 和ID爲 9 的商品,下面三種寫法均可以:

POST /_bulk
{"create":{"_index":"goods","_type":"books","_id":"8"}}
{"name":"more Basic","salesPrice":1900,"onlineStock":134}
{"create":{"_index":"goods","_type":"books","_id":"9"}}
{"name":"more Pascal","salesPrice":1200,"onlineStock":234}
複製代碼

POST /goods/_bulk
{"create":{"_type":"books","_id":"8"}}
{"name":"more Basic","salesPrice":1900,"onlineStock":134}
{"create":{"_type":"books","_id":"9"}}
{"name":"more Pascal","salesPrice":1200,"onlineStock":234}
複製代碼

POST /goods/books/_bulk
{"create":{"_id":"8"}}
{"name":"more Basic","salesPrice":1900,"onlineStock":134}
{"create":{"_id":"9"}}
{"name":"more Pascal","salesPrice":1200,"onlineStock":234}
複製代碼

須要注意的是,利用bulk API 進行批量操做的時候,若其中一個操做失敗,只會在操做結果中告訴咱們,並不會影響到其餘的操做,例如,如今 ES 中存在商品ID 爲10的商品,不存在商品ID 爲11的商品,此時運行

POST /goods/books/_bulk
{"create":{"_id":"10"}}
{"name":"more Basic","salesPrice":1900,"onlineStock":134}
{"create":{"_id":"11"}}
{"name":"more Pascal 11","salesPrice":1200,"onlineStock":234}
複製代碼

運行結果爲

{
  "took" : 13,
  "errors" : true,
  "items" : [
    {
      "create" : {
        "_index" : "goods",
        "_type" : "books",
        "_id" : "10",
        "status" : 409,
        "error" : {
          "type" : "version_conflict_engine_exception",
          "reason" : "[books][10]: version conflict, document already exists (current version [1])",
          "index_uuid" : "UE-4WzIDTHqd7RpGX2QbMQ",
          "shard" : "1",
          "index" : "goods"
        }
      }
    },
    {
      "create" : {
        "_index" : "goods",
        "_type" : "books",
        "_id" : "11",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 4,
        "_primary_term" : 3,
        "status" : 201
      }
    }
  ]
}
複製代碼

"errors" : true 代表這次 bulk 操做發生了error,相應位置的 item指出了具體的錯誤信息。

4). 語法4,利用 bulk API 的index 操做批量建立document
語法同bulk API 的create 操做,這裏再也不細說,直接舉例子

例如,批量建立ID爲 8 和ID爲 9 的商品:

POST /goods/books/_bulk
{"index":{"_id":"8"}}
{"name":"more Basic","salesPrice":1900,"onlineStock":134}
{"index":{"_id":"9"}}
{"name":"more Pascal","salesPrice":1200,"onlineStock":234}
複製代碼

2.查詢文檔

1). 語法1,查詢特定ID的document 信息:

GET /index_name/type_name/id
複製代碼

若只想查詢商品的某個字段,可在id後拼接「?_source=field _name」,不然默認 _source 會返回全部的字段。

例如,查詢ID爲1的商品的名稱:

GET /goods/books/1?_source=name
複製代碼

2). 語法2,批量查詢:

GET /_mget
{
  "docs": [
      {
        "_index""index_name1",
        "_type""type_name1",
        "_id""id1"
      },
      {
        "_index""index_name2",
        "_type""type_name2",
        "_id""id2"
      }
    ......
    ]
}
複製代碼

若index_name 相同,則能夠簡寫爲

GET /index_name/_mget
{
  "docs": [
      {
        "_type""type_name1",
        "_id""id1"
      },
      {
        "_type""type_name2",
        "_id""id2"
      }
    ......
    ]
}
複製代碼

若index_name 和 type_name 均相同,則能夠進一步簡寫爲

GET /index_name/type_name/_mget
{
  "ids": ["id1""id2"]
}
複製代碼

例如,查詢ID爲1 和 2的商品信息,下面三種寫法均可以:

GET /_mget
{
  "docs": [
      {
        "_index""goods",
        "_type""books",
        "_id""1"
      },
      {
        "_index""goods",
        "_type""books",
        "_id""2"
      }
    ]
}
複製代碼

GET /goods/_mget
{
  "docs": [
      {
        "_type""books",
        "_id""1"
      },
      {
        "_type""books",
        "_id""2"
      }
    ]
}
複製代碼

GET /goods/books/_mget
{
  "ids": ["1""2"]
}
複製代碼

3). 語法3,利用search API進行查詢,後面會有單獨一篇文章進行講解。

3.修改文檔

1). 語法1,PUT 方法,修改時所攜帶的field 會將document 已有的field 所有替換掉,即document 會進行全量替換,語法同建立文檔:

PUT /index_name/type_name/id
{
    "Json format data"
}
複製代碼

舉例:
先新增一條商品信息:

PUT /goods/books/1
{
  "name":"effective java",
  "purchasePrice":7800,
  "salesPrice":12000,
  "currencyUnit":"cent",
  "desc":"Joshua Bloch",
  "onlineStock":999
}
複製代碼

而後修改商品:

PUT /goods/books/1
{
  "name":"More Effective Java",
  "salesPrice":13000,
  "currencyUnit":"cent"
}
複製代碼

運行結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
複製代碼

從結果中能夠看到version版本號更新爲2,執行的操做是updated。此時執行查詢操做,你會發現此document 僅剩下修改後的3個field 了。

其實document 是不可變的,這種方式修改 document 時,會對 document 創建一個新的索引,而後在新的索引中賦值全部的內容,老的document 會被標記爲deleted,等待後續 ES 對其進行真正的物理刪除。

既然全量替換的語法和建立文檔的語法是相同的,那麼若是我此刻就是想建立文檔,而非全量替換文檔,那我應該怎麼作呢?別慌,問題不大,ES 提供了這個功能。

PUT /index_name/type_name/id?op_type=create
{
    "Json format data"
}
複製代碼

或者

PUT /index_name/type_name/id/_create
{
    "Json format data"
}
複製代碼

便可實現強制建立文檔的功能。

2). 語法2,修改時攜帶哪一個field,僅替換文檔中相同的field

POST /index_name/type_name/id/_update
{
    "doc": {
        "Json format data"
    }
}
複製代碼

舉例:
先新增一條商品信息:

PUT /goods/books/2
{
  "name":"effective python",
  "purchasePrice":5000,
  "salesPrice":6000,
  "currencyUnit":"cent",
  "desc":"Brett Slatkin",
  "onlineStock":666
}
複製代碼

而後修改商品:

POST /goods/books/2/_update
{
  "doc": {
    "name":"more effective python3",
    "salesPrice":8000,
    "desc":"handsome Brett Slatkin"
  }
}
複製代碼

運行結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "2",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
複製代碼

從結果中能夠看到version版本號更新爲2,執行的操做也是updated。此時執行查詢操做,你會發現此document中其餘field 保持不變,只有POST方法中攜帶的那三個field 發生了改變。這是與語法1很大的一個區別。

其實POST 這種方式的部分替換其內部執行過程和語法1的全量替換很像,ES會建立一個新的document,使用舊document的信息,而後ES 會將POST傳遞過來的json 更新到新的document 中,不過僅更新key 匹配的json 串,而後ES 會將舊的document 標記爲deleted,將更新後的新的document 存入ES 中,這些操做都發生在一個shard中。

3). 語法3,利用bulk API 的index 操做,index 操做既能夠批量建立文檔,也能夠全量替換文檔,這裏再也不舉例。

4). 語法4,利用bulk API 的update 操做,效果同 POST 操做,僅修改攜帶的field 域
例如,修改商品ID爲8 和 9的商品的商品名稱和在線庫存

POST /goods/books/_bulk
{"update":{"_id":"8"}}
{"doc":{"name":"more Basic update","salesPrice":2300}}
{"update":{"_id":"9"}}
{"doc":{"name":"more Pascal update","onlineStock":12}}
複製代碼

4.刪除文檔

1). 語法1

DELETE /index_name/type_name/id
複製代碼

當執行delete 操做的時候,ES 並不會馬上將document 進行物理刪除,而是先將document 標記爲deleted,待後續ES 中數據愈來愈多時纔會對標記爲deleted的document 進行物理刪除。

有時你會發現先將document 進行delete操做,而後又新建該document 時,新建的document 實際上是基於已刪的document 信息的,新建document 的_version是基於已刪document 的 _version而後又加了1。

舉例:新建ID爲5的商品:

PUT /goods/books/5
{
  "name""test book"
}
複製代碼

結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "5",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
複製代碼

刪除該商品:

DELETE /goods/books/5
複製代碼

結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "5",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}
複製代碼

能夠看到delete操做的結果中,_version 爲2,此時再新建該商品:

PUT /goods/books/5
{
  "name""test book"
}
複製代碼

結果:

{
  "_index" : "goods",
  "_type" : "books",
  "_id" : "5",
  "_version" : 3,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 9,
  "_primary_term" : 1
}
複製代碼

能夠看到新建document 的 _version爲3,即驗證了上述咱們所說的狀況。

2). 語法2,利用bulk API 的delete操做

action: { metadata }}\n
複製代碼

舉例,刪除商品ID爲8和9的商品

POST /_bulk
{"delete":{"_index":"goods","_type":"books","_id":"8"}}
{"delete":{"_index":"goods","_type":"books","_id":"9"}}
複製代碼

POST /goods/_bulk
{"delete":{"_type":"books","_id":"8"}}
{"delete":{"_type":"books","_id":"9"}}
複製代碼

POST /goods/books/_bulk
{"delete":{"_id":"8"}}
{"delete":{"_id":"9"}}
複製代碼

固然bulk API的create、index、update、delete操做能夠一塊兒使用,一樣任意一個操做失敗是不會影響到其餘操做的,只是會在返回日誌中說明。

若是這篇文章對你有幫助或啓發,歡迎關注和轉發,你的關注和轉發是對我最大的支持。
若是你有什麼疑問想要免費vip服務,歡迎掃描下方二維碼,關注便可得到1v1免費vip服務。

相關文章
相關標籤/搜索