Elasticsearch集群知識筆記

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Elasticsearch集群知識筆記

Elasticsearch內部提供了一個rest接口用于查看集群內部的健康狀況:

curl -XGET http://localhost:9200/_cluster/health

response結果:

{
"cluster_name": "format-es",
"status": "green",
...
}

這里的status有3種狀態,分別是green(所有主分片和復制分片都可用),yellow(所有主分片可用,但不是所有復制分片都可用)和red(不是所有主分片可用)。

分片(Shard)

Elasticsearch中的索引(index)是由分片(shard)構成的。

比如我們集群中有個索引users,該索引由3個分片組成,那么這個users索引中的文檔數據將分布在這3個分片中。

users索引中的文檔是根據下面這個規則確定該文檔屬于哪個分片:

shard = hash(routing) % number_of_primary_shards // routing值默認是文檔的_id,number_of_primary_shards是索引的主分片個數

這個routing默認是文檔的_id,可以自定義(文章后面部分會舉例說明)。

這3個分片可以進行復制,復制是為了實現容錯性,比如復制1份,那么一共就需要6個分片(3個主分片+3個主分片復制出來的復制分片)。

users索引的創建命令(主分片3個,復制1份):

curl -XPUT http://localhost:9200/users -d '
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
'

創建完users索引之后,es集群(單節點)分片情況如下:

由于users索引有3個分片,es內部會創建出3個分片,分別是P0、P1和P2(大寫P指的是primary),且這3個分片都是主分片。users索引需要對分片進行復制1份,所以這3個主分片都需要復制1份,分別對應R0、R1和R2這3個復制分片(大寫R指的是replica)。這個時候我們的集群只有1個節點node-1,所以復制分片并沒有起作用(如果復制分片和主分片在同一個節點了,那么這個復制分片的意義就不存在了。復制分片的意義在于容錯性,當一個節點掛了,另一個節點上的分片可以代替掛掉節點上的分片)。

查看健康狀態:

curl -XGET http://localhost:9200/_cluster/health

response結果:

{
"cluster_name": "format-es",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 3,
"active_shards": 3,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 3,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 50
}

這里可以看到,集群的狀態變成了yellow。這是因為users索引中的分片需要復制1份,但是沒有足夠的機器用來存儲復制出來的復制分片,還有其它的一些字段比如unassigned_shards字段為3,對應R0、R1和R2這3個未分配的復制分片。

在集群中加入節點node-2,查看健康狀況(這里使用偽集群。node-1節點對應9200端口的進程,node-2節點對應9201端口的進程):

curl -XGET http://localhost:9200/_cluster/health

response結果:

{
"cluster_name": "format-es",
"status": "green",
"timed_out": false,
"number_of_nodes": 2,
"number_of_data_nodes": 2,
"active_primary_shards": 3,
"active_shards": 6,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100
}

主分片和復制分片均可用,status為green。

此時,es集群分片情況如下:

這個時候es集群由2個節點node-1和node-2組成,并且這2個節點上具有主分片和復制分片,具有容錯性。

我們往users索引中插入一條文檔:

curl -XPOST http://localhost:9200/users/normal -d '
{
"name" : "Format",
"age" : 111
}
'

返回:

{
"_index": "users",
"_type": "normal",
"_id": "AV0hs4LnkXxVJ5DURwXr",
"_version": 1,
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"created": true
}

從返回的信息中可以看到,這個文檔已經被創建成功,并且2個分片都成功。id由es內部自動創建,值為AV0hs4LnkXxVJ5DURwXr。

讀取id為AV0hs4LnkXxVJ5DURwXr的文檔:

curl -XGET http://localhost:9200/users/normal/AV0hs4LnkXxVJ5DURwXr
# 結果
{
"_index": "users",
"_type": "normal",
"_id": "AV0hs4LnkXxVJ5DURwXr",
"_version": 1,
"found": true,
"_source": {
"name": "Format",
"age": 111
}
}

這個時候如果節點node-1掛了,讀取數據:

curl -XGET http://localhost:9201/users/normal/AV0hs4LnkXxVJ5DURwXr
# 結果
{
"_index": "users",
"_type": "normal",
"_id": "AV0hs4LnkXxVJ5DURwXr",
"_version": 1,
"found": true,
"_source": {
"name": "Format",
"age": 111
}
}

在節點node-1已經掛了的情況下還是讀取到了之前插入的文檔。這是因為我們users索引會復制2份,node-1節點雖然已經掛了,但是node-2節點上這個文檔的數據還在,所以文檔會被讀取到。

在node-1節點掛掉的情況下,再次插入一條文檔:

curl -XPOST http://localhost:9201/users/normal -d '
{
"name" : "Jim",
"age" : 66
}
'

返回:

{
"_index": "users",
"_type": "normal",
"_id": "AV0qMto5dJHprgu99sSN",
"_version": 1,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"created": true
}

這里看到返回的數據中,這個文檔對應的分片只有1個成功插入,因為另1個分片對應的節點已經掛了。

然后讀取這個新插入的文檔:

curl -XGET http://localhost:9201/users/normal/AV0qMto5dJHprgu99sSN
# 結果
{
"_index": "users",
"_type": "normal",
"_id": "AV0qMto5dJHprgu99sSN",
"_version": 1,
"found": true,
"_source": {
"name": "Jim",
"age": 66
}
}

然后node-1節點恢復(節點恢復之后,es內部會自動從數據全的分片中復制數據到數據少的分片上,保證高可用),然后讀取數據:

curl -XGET http://localhost:9200/users/normal/AV0qMto5dJHprgu99sSN
# 結果
{
"_index": "users",
"_type": "normal",
"_id": "AV0qMto5dJHprgu99sSN",
"_version": 1,
"found": true,
"_source": {
"name": "Jim",
"age": 66
}
}

ES中文檔的新建、刪除和修改都是先在主分片上完成的,在主分片上完成這些操作以后,才會進行復制操作。比如有3個節點node-1、node-2和node-3,索引blogs有2個主分片,并且復制2份,集群結構如下:

當進行新建文檔的時候過程如下:

  1. 客戶端給master節點node-1發送新建文檔的請求
  2. node-1節點根據文檔的_id,確定該文檔屬于屬于分片1。分片1的主分片在節點node-2上,故將請求轉發到node-2
  3. node-2上的主分片P1處理文檔成功,然后轉發請求到node-1和node-3節點上的復制節點上。當所有的復制節點報告成功后,node-2節點報告成功到請求的節點,請求節點再返回給客戶端

當進行檢索文檔的時候過程如下:

  1. 客戶端給master節點node-1發送檢索文檔的請求
  2. node-1節點根據文檔的_id,確定該文檔屬于分片0。分片0在3個節點中都存在,本次請求中使用節點node-2,于是將請求轉發給node-2節點
  3. node-2節點得到文檔數據,并返回給node-1節點,node-1節點返回給客戶端

這里es集群會使用輪詢的策略對讀取不同節點上的分片中的文檔數據,比如針對上圖中的查詢,下次查詢就會讀取node-3節點上的R0分片中的文檔。

當對文檔進行局部更新的時候過程如下:

  1. 客戶端給master節點node-1發送局部更新文檔的請求
  2. node-1節點根據文檔的_id,確定該文檔屬于分片1,并發現找到分片1的主分片在node-2節點上,轉發請求到node-2節點上
  3. node-2節點在主分片P1中找出對應id的文檔,修改文檔內部的_source屬性,之后對文檔重建索引。如果這個文檔已經被其它進程修改,會重試步驟3 retry_on_conflict 次數(retry_on_conflict可通過參數設置)
  4. 如果步驟3執行成功,node-2節點轉發新版本的文檔給node-1和node-3節點上的復制分片,這2個節點對文檔進行重建索引。一旦node-1和node-3節點上的復制分片處理成功,node-2節點返回成功給node-1節點,node-1節點返回給客戶端

節點(Node)

在分布式集群情況下,ES中的節點可分為4類:

  1. master節點:配置文件中node.master屬性為true(默認為true),就有資格被選為master節點,master節點用于控制整個集群的操作。比如創建或刪除索引,管理其它非master節點等
  2. data節點:配置文件中node.data屬性為true(默認為true),就有資格被設置成data節點,data節點主要用于執行數據相關的操作。比如文檔的CRUD
  3. 客戶端節點:配置文件中node.master屬性和node.data屬性均為false。該節點不能作為master節點,也不能作為data節點。可以作為客戶端節點,用于響應用戶的請求,把請求轉發到其他節點
  4. 部落節點:當一個節點配置tribe.*的時候,它是一個特殊的客戶端,它可以連接多個集群,在所有連接的集群上執行搜索和其他操作

查詢集群狀態的Rest接口

可以通過es內部提供的rest接口查看master節點:

curl -XGET http://localhost:9200/_cat/master?v
id host ip node
9FINsHCpTKqcpFlnnA4Yww 10.1.251.164 10.1.251.164 node-1

查看節點信息:

curl -XGET http://localhost:9200/_cat/nodes?v
host ip heap.percent ram.percent load node.role master name
10.1.251.164 10.1.251.164 6 100 5.48 d * node-1
10.1.251.164 10.1.251.164 6 100 5.48 d m node-3
10.1.251.164 10.1.251.164 7 100 5.48 d m node-2

或者使用head插件查看節點情況。圖中帶有五角星的節點是master,這里users索引有3個主分片和3個復制分片(綠色框外部加粗的邊框就是主分片,否則就是復制分片):

如果我們的集群上node-1節點由于硬盤容量不足導致不可用時,head插件情況如下(3個復制節點未被分配,健康狀況為黃色):

也可使用es內部的rest接口查看分片信息:

curl -XGET http://localhost:9200/_cat/shards?v
index shard prirep state docs store ip node
users 1 p STARTED 1 3.3kb 10.1.251.164 node-2
users 1 r UNASSIGNED
users 2 p STARTED 0 159b 10.1.251.164 node-2
users 2 r UNASSIGNED
users 0 p STARTED 2 6.6kb 10.1.251.164 node-3
users 0 r UNASSIGNED

routing參數決定如何分片(可以在index、get、delete、update、bulk等方法中使用),我們覆蓋默認的routing為_id的默認策略:

# 執行10次
curl -XPOST http://localhost:9200/users/normal?routing=1 -d '
{
"name" : "Format345",
"age" : 456
}
'
# 執行1次
curl -XPOST http://localhost:9200/users/normal -d '
{
"name" : "Format345",
"age" : 456
}
'
# 使用routing參數得到文檔的結果(多了個_rouring屬性)
{
"_index": "users",
"_type": "normal",
"_id": "AV07AubA6HDSJNRJle0i",
"_version": 1,
"_routing": "1",
"found": true,
"_source": {
"name": "Format345",
"age": 456
}
}
# 查詢文檔分布情況(前面10次分布到了P2分片,后面1次分布到了P1分片)
curl -XGET http://localhost:9200/_cat/shards?v
index shard prirep state docs store ip node
users 1 p STARTED 2 3.3kb 10.1.251.164 node-2
users 1 r UNASSIGNED
users 2 p STARTED 10 159b 10.1.251.164 node-2
users 2 r UNASSIGNED
users 0 p STARTED 2 6.6kb 10.1.251.164 node-3
users 0 r UNASSIGNED

官網上有更多關于_cat api和_cluster api相關的文檔。

文檔操作

es中文檔的操作可以使用其內部提供的rest接口,使用過程中可以指定一些參數修改默認行為。

1.replication:用于設置復制分片的處理過程是同步還是異步。默認值是sync(主分片需要等待復制分片全部處理完畢),也可以設置成async(主分片不需要等待復制分片的處理過程,但是還是會轉發請求給復制分片,這個轉發過程是異步的)。該參數在2.0.0版本后已經被廢棄,因為異步轉發給復制分片的話,不知道復制分片是否成功與否,而且復制分片在還沒有處理完成的情況下由于一直過來的異步請求而導致es過載,不建議使用async

2.consistency:寫文檔的一致性參數,可以設置成one,quorum和all;分別表示主分片可用即可、過半分片可用[公式:int( (primary + number_of_replicas) / 2 ) + 1]以及全部分片可用。比如有個blogs索引,有3個主分片,并且復制2份,當集群中的1個節點掛了,并使用all的話,將會拋出異常:

curl -XPOST http://localhost:9200/blogs/normal?consistency=all -d '
{
"name" : "POST-1"
}
'
# 一分鐘后拋出異常
{
"error": {
"root_cause": [
{
"type": "unavailable_shards_exception",
"reason": "[blogs][0] Not enough active copies to meet write consistency of [ALL] (have 2, needed 3). Timeout: [1m], request: [index {[blogs][normal][AV1AF1FEl7qPpRBCQMV7], source[{\n \"name\" : \"POST-1\"\n}]}]"
}
],
"type": "unavailable_shards_exception",
"reason": "[blogs][0] Not enough active copies to meet write consistency of [ALL] (have 2, needed 3). Timeout: [1m], request: [index {[blogs][normal][AV1AF1FEl7qPpRBCQMV7], source[{\n \"name\" : \"POST-1\"\n}]}]"
},
"status": 503
}

使用默認的quorum策略:

curl -XPOST http://localhost:9200/blogs/normal -d '
{
"name" : "POST-1"
}
# 由于集群中的節點掛了1個,所分片只有2個success
{
"_index": "blogs",
"_type": "normal",
"_id": "AV1AckLfl7qPpRBCQMV_",
"_version": 1,
"_shards": {
"total": 3,
"successful": 2,
"failed": 0
},
"created": true
}
'

consistency參數在5.0.0版本已經被棄用

3.timeout:當分片不足的時候,es等待的時間(等待節點重新啟動,分片恢復),默認為1分鐘,可以進行修改,改成10秒:

curl -XPOST http://localhost:9200/blogs/normal?consistency=all&timeout=10s -d '
{
"name" : "POST-1"
}
'
# 10秒后拋出異常
{
"error": {
"root_cause": [
{
"type": "unavailable_shards_exception",
"reason": "[blogs][1] Not enough active copies to meet write consistency of [ALL] (have 2, needed 3). Timeout: [10s], request: [index {[blogs][normal][AV1AdXxsl7qPpRBCQMWB], source[{\n \"name\" : \"POST-1\"\n}]}]"
}
],
"type": "unavailable_shards_exception",
"reason": "[blogs][1] Not enough active copies to meet write consistency of [ALL] (have 2, needed 3). Timeout: [10s], request: [index {[blogs][normal][AV1AdXxsl7qPpRBCQMWB], source[{\n \"name\" : \"POST-1\"\n}]}]"
},
"status": 503
}

4.version

es中每個文檔都有對應的版本信息,可以使用version版本參數用來實現并發情況下的樂觀鎖機制:

# 新建一個文檔
curl -XPUT http://localhost:9200/blogs/normal/format-001 -d '
{
"name" : "format-post-001"
}
'
# 結果
{
"_index": "blogs",
"_type": "normal",
"_id": "format-001",
"_version": 1,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"created": true
}
# id為format-001的文檔目前的version為1,進行更新
# 用version為2去更新
curl -XPUT http://localhost:9200/blogs/normal/format-001?version=2 -d '
{
"name" : "format-post-001-001"
}
'
# 報錯,版本沖突
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[normal][format-001]: version conflict, current [1], provided [2]",
"shard": "0",
"index": "blogs"
}
],
"type": "version_conflict_engine_exception",
"reason": "[normal][format-001]: version conflict, current [1], provided [2]",
"shard": "0",
"index": "blogs"
},
"status": 409
}
# 用version為1去更新
curl -XPUT http://localhost:9200/blogs/normal/format-001?version=1 -d '
{
"name" : "format-post-001-001"
}
'
# 更新成功,文檔版本變成2
{
"_index": "blogs",
"_type": "normal",
"_id": "format-001",
"_version": 2,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"created": false
}

5.op_type:可以指定本次操作的類型,比如create操作。

# 創建一個id為1,type為normal,在blogs索引中的文檔
curl -XPUT http://localhost:9200/blogs/normal/1?op_type=create -d '
{
"name" : "POST-2"
}
'
{
"_index": "blogs",
"_type": "normal",
"_id": "1",
"_version": 1,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"created": true
}
# 繼續調用同一個操作
curl -XPUT http://localhost:9200/blogs/normal/1?op_type=create -d '
{
"name" : "POST-2"
}
'
# 報錯,文檔已經存在
{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[normal][1]: document already exists",
"shard": "0",
"index": "blogs"
}
],
"type": "document_already_exists_exception",
"reason": "[normal][1]: document already exists",
"shard": "0",
"index": "blogs"
},
"status": 409
}

可以不使用op_type操作,在url中指定。這兩種方法效果是一樣的

http://localhost:9200/blogs/normal/1/_create 效果跟 http://localhost:9200/blogs/normal/1?op_type=create 是一樣的。

目前支持的op_type有create(只支持創建文檔)和index(支持創建和更新文檔)。

6.wait_for_active_shards

在5.0.0版本新引入的一個參數,表示等待活躍的分片數。作用跟consistency類似,可以設置成all或者任意正整數。

比如在這種場景下:集群中有3個節點node-1、node-2和node-3,并且索引中的分片需要復制3份。那么該索引一共擁有4個分片,包括1個主分片和3個復制分片。

默認情況下,索引操作只需要等待主分片可用(wait_for_active_shards為1)即可。

如果node-2和node-3節點掛了,索引操作是不會受影響的(wait_for_active_shards默認為1);如果設置了wait_for_active_shards為3,那么需要3個節點全部存活;如果設置了wait_for_active_shards為4或者all(一共4個分片,4和all是一樣的效果),那么該集群中的索引操作永遠都會失敗,因為集群一共就3個節點,不能處理所有的4個分片。

比如設置成all,則會拋出如下錯誤:

{
"error": {
"root_cause": [
{
"type": "unavailable_shards_exception",
"reason": "[blogs][2] Not enough active copies to meet shard count of [ALL] (have 3, needed 4). Timeout: [1m], request: [index {[blogs][normal][AV1QVDz3RpA5iuXn159C], source[{\n \"name\" : \"POST-1\"\n}]}]"
}
],
"type": "unavailable_shards_exception",
"reason": "[blogs][2] Not enough active copies to meet shard count of [ALL] (have 3, needed 4). Timeout: [1m], request: [index {[blogs][normal][AV1QVDz3RpA5iuXn159C], source[{\n \"name\" : \"POST-1\"\n}]}]"
},
"status": 503
}

wait_for_active_shards的默認值可以在定義索引的時候進行設置,也可以動態地進行修改:

curl -XPUT http://localhost:9200/blogs/_settings -d '
{
"index.write.wait_for_active_shards": 3
}
'

7.自動生成id

創建文檔的時候,可以不指定id,es會自動為你生成1個id,需要注意的話需要使用POST方式,而不是PUT方式。

curl -XPOST http://localhost:9200/blogs/normal -d '
{
"name" : "my-post"
}
'
{
"_index": "blogs",
"_type": "normal",
"_id": "AV1Pj6MdAuPf3r3i0ysL", # 自動生成的id
"_version": 1,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"created": true
}

8.文檔的局部更新

# 新建文檔
curl -XPUT http://localhost:9200/blogs/normal/format-doc-001 -d '
{
"title" : "springboot in action",
"author" : "Format"
}
'
# 執行全更新操作
curl -XPUT http://localhost:9200/blogs/normal/format-doc-001 -d '
{
"create_at": "2017-07-18"
}
'
# 獲取文檔
curl -XGET http://localhost:9200/blogs/normal/format-doc-001
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-001",
"_version": 2,
"found": true,
"_source": {
"create_at": "2017-07-18"
}
}
# 使用文檔局部更新
curl -XPOST http://localhost:9200/blogs/normal/format-doc-001/_update -d '
{
"doc": {
"title" : "springboot in action",
"author" : "Format"
}
}
'
# 獲取文檔
curl -XGET http://localhost:9200/blogs/normal/format-doc-001
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-001",
"_version": 3,
"found": true,
"_source": {
"create_at": "2017-07-18",
"author": "Format",
"title": "springboot in action"
}
}
# 使用腳本局部更新
curl -XPOST http://localhost:9200/blogs/normal/format-doc-001/_update -d '
{
"script" : "ctx._source.views = 0; ctx._source.tags = [new_tag]",
"params": {
"new_tag": "java"
}
}
'
# 獲取文檔
curl -XGET http://localhost:9200/blogs/normal/format-doc-001
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-001",
"_version": 3,
"found": true,
"_source": {
"create_at": "2017-07-18",
"author": "Format",
"title": "springboot in action",
"tags": [
"java"
],
"views": 0
}
}
# 使用腳本局部更新新創建的文檔
curl -XPOST http://localhost:9200/blogs/normal/format-doc-002/_update -d '
{
"script" : "ctx._source.views+=1"
}
'
# 報錯,因為id為format-doc-002的文檔不存在
{
"error": {
"root_cause": [
{
"type": "document_missing_exception",
"reason": "[normal][format-doc-002]: document missing",
"shard": "0",
"index": "blogs"
}
],
"type": "document_missing_exception",
"reason": "[normal][format-doc-002]: document missing",
"shard": "0",
"index": "blogs"
},
"status": 404
}
# 加上upsert參數(設置字段的初始值)
curl -XPOST http://localhost:9200/blogs/normal/format-doc-002/_update -d '
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 1
}
}
'
# 獲取文檔
curl -XGET http://localhost:9200/blogs/normal/format-doc-002
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-002",
"_version": 1,
"found": true,
"_source": {
"views": 1
}
}

9.檢索多個文檔(Multi Get API)

可以在一個請求中獲得多個文檔數據。

# 在所有索引中執行mget,在參數中指定索引
curl -XGET http://localhost:9200/_mget -d '
{
"docs" : [
{
"_index" : "blogs",
"_type" : "normal",
"_id" : "format-doc-001"
},
{
"_index" : "blogs",
"_type" : "normal",
"_id" : "format-doc-002"
}
]
}
'
# 結果
{
"docs": [
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-001",
"_version": 3,
"found": true,
"_source": {
"create_at": "2017-07-18",
"author": "Format",
"title": "springboot in action",
"tags": [
"java"
],
"views": 0
}
},
{
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-002",
"_version": 1,
"found": true,
"_source": {
"views": 1
}
}
]
}
# 基于特定的索引做mget
curl -XGET http://localhost:9200/blogs/_mget -d '
{
"docs" : [
{
"_type" : "normal",
"_id" : "format-doc-001"
},
{
"_type" : "normal",
"_id" : "format-doc-002"
}
]
}
'
# 基于特定的索引和類型做mget
curl -XGET http://localhost:9200/blogs/normal/_mget -d '
{
"docs" : [
{
"_id" : "format-doc-001"
},
{
"_id" : "format-doc-002"
}
]
}
'
# 簡化版的基于特定的索引和類型做mget
curl -XGET http://localhost:9200/blogs/normal/_mget -d '
{
"ids": ["format-doc-001", "format-doc-002"]
}
'
# 過濾source中的屬性
curl -XGET http://localhost:9200/_mget -d '
{
"docs" : [
{
"_index": "blogs",
"_type": "normal",
"_id" : "format-doc-001",
"_source": ["title", "author"]
},
{
"_index": "blogs",
"_type": "normal",
"_id" : "format-doc-002",
"_source": false
},
{
"_index": "blogs",
"_type": "normal",
"_id" : "format-doc-003",
"_source": {
"include": ["title"],
"exclude": ["author"]
}
}
]
}
'

10.批量操作(bulk)

批量操作可以實現同一個請求操作多個文檔的過程。需要注意的是bulk操作Http Body中的格式,對文檔進行處理的話需要使用換行。比如創建新文檔,更新文檔都需要使用換行把創建目錄和文檔數據進行分割。不同的操作也需要用換行進行分割,比如創建文檔和刪除文檔。

# 3個批量操作,分別是創建文檔,更新文檔以及刪除文檔
# 創建文檔的時候需要使用換行分割開創建目錄和文檔數據
# 更新文檔的時候也需要使用換行分割開創建目錄和文檔數據
# 最后一個操作需要使用換行結束
curl -XPOST http://localhost:9200/_bulk --d '
{ "create": { "_index": "blogs", "_type": "normal", "_id": "format-bulk-doc-001" } }
{ "title": "Hadoop in action", "author": "Chuck Lam" }
{ "update": { "_index": "blogs", "_type": "normal", "_id": "format-bulk-doc-001" } }
{ "doc": { "create_at": "2017-07-19" } }
{ "delete": { "_index": "blogs", "_type": "normal", "_id": "format-doc-002" } }
'
# 結果
{
"took": 695,
"errors": false,
"items": [
{
"create": {
"_index": "blogs",
"_type": "normal",
"_id": "format-bulk-doc-001",
"_version": 1,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"status": 201
}
},
{
"update": {
"_index": "blogs",
"_type": "normal",
"_id": "format-bulk-doc-001",
"_version": 2,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"status": 200
}
},
{
"delete": {
"_index": "blogs",
"_type": "normal",
"_id": "format-doc-002",
"_version": 2,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"status": 200,
"found": true
}
}
]
}

轉載于:https://www.cnblogs.com/Henry-pan/p/7242594.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391894.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391894.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391894.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Item 14 In public classes, use accessor methods, not public fields

在public類中使用訪問方法,而非公有域 這標題看起來真晦澀。。解釋一下就是,如果類變成public的了--->那就使用getter和setter,不要用public成員。 要注意它的前提,如果是private的class(內部類..)或者p…

子集和與一個整數相等算法_背包問題的一個變體:如何解決Java中的分區相等子集和問題...

子集和與一個整數相等算法by Fabian Terh由Fabian Terh Previously, I wrote about solving the Knapsack Problem (KP) with dynamic programming. You can read about it here.之前,我寫過有關使用動態編程解決背包問題(KP)的文章。 你可以在這里閱讀 。 Today …

matplotlib圖表介紹

Matplotlib 是一個python 的繪圖庫,主要用于生成2D圖表。 常用到的是matplotlib中的pyplot,導入方式import matplotlib.pyplot as plt 一、顯示圖表的模式 1.plt.show() 該方式每次都需要手動show()才能顯示圖表,由于pycharm不支持魔法函數&a…

到2025年將保持不變的熱門流行技術

重點 (Top highlight)I spent a good amount of time interviewing SMEs, data scientists, business analysts, leads & their customers, programmers, data enthusiasts and experts from various domains across the globe to identify & put together a list that…

spring—SpringMVC的請求和響應

SpringMVC的數據響應-數據響應方式 頁面跳轉 直接返回字符串 RequestMapping(value {"/qq"},method {RequestMethod.GET},params {"name"})public String method(){System.out.println("controller");return "success";}<bea…

Maven+eclipse快速入門

1.eclipse下載 在無外網情況下&#xff0c;無法通過eclipse自帶的help-install new software輸入url來獲取maven插件&#xff0c;因此可以用集成了maven插件的免安裝eclipse(百度一下有很多)。 2.jdk下載以及環境變量配置 JDK是向前兼容的&#xff0c;可在Eclipse上選擇編譯器版…

源碼閱讀中的收獲

最近在做短視頻相關的模塊&#xff0c;于是在看 GPUImage 的源碼。其實有一定了解的伙伴一定知道 GPUImage 是通過 addTarget 鏈條的形式添加每一個環節。在對于這樣的設計贊嘆之余&#xff0c;想到了實際開發場景下可以用到的場景&#xff0c;借此分享。 我們的項目中應該有很…

馬爾科夫鏈蒙特卡洛_蒙特卡洛·馬可夫鏈

馬爾科夫鏈蒙特卡洛A Monte Carlo Markov Chain (MCMC) is a model describing a sequence of possible events where the probability of each event depends only on the state attained in the previous event. MCMC have a wide array of applications, the most common of…

PAT乙級1012

題目鏈接 https://pintia.cn/problem-sets/994805260223102976/problems/994805311146147840 題解 就比較簡單&#xff0c;判斷每個數字是哪種情況&#xff0c;然后進行相應的計算即可。 下面的代碼中其實數組是不必要的&#xff0c;每取一個數字就可以直接進行相應計算。 // P…

我如何在昌迪加爾大學中心組織Google Hash Code 2019

by Neeraj Negi由Neeraj Negi 我如何在昌迪加爾大學中心組織Google Hash Code 2019 (How I organized Google Hash Code 2019 at Chandigarh University Hub) This is me !!! Neeraj Negi — Google HashCode Organizer這就是我 &#xff01;&#xff01;&#xff01; Neeraj …

leetcode 665. 非遞減數列(貪心算法)

給你一個長度為 n 的整數數組&#xff0c;請你判斷在 最多 改變 1 個元素的情況下&#xff0c;該數組能否變成一個非遞減數列。 我們是這樣定義一個非遞減數列的&#xff1a; 對于數組中所有的 i (0 < i < n-2)&#xff0c;總滿足 nums[i] < nums[i 1]。 示例 1: …

django基于存儲在前端的token用戶認證

一.前提 首先是這個代碼基于前后端分離的API,我們用了django的framework模塊,幫助我們快速的編寫restful規則的接口 前端token原理: 把(token加密后的字符串,keyname)在登入后發到客戶端,以后客戶端再發請求,會攜帶過來服務端截取(token加密后的字符串,keyname),我們再利用解密…

數據分布策略_有效數據項目的三種策略

數據分布策略Many data science projects do not go into production, why is that? There is no doubt in my mind that data science is an efficient tool with impressive performances. However, a successful data project is also about effectiveness: doing the righ…

cell 各自的高度不同的時候

1, cell 根據文字、圖片等內容&#xff0c;確定自己的高度。每一個cell有自己的高度。 2&#xff0c;tableView 初始化 現實的時候&#xff0c;不是從第一個cell開始顯示&#xff0c;&#xff08;從第二個&#xff1f;&#xff09;&#xff0c;非非正常顯示。 a:cell 的高度問題…

leetcode 978. 最長湍流子數組(滑動窗口)

當 A 的子數組 A[i], A[i1], …, A[j] 滿足下列條件時&#xff0c;我們稱其為湍流子數組&#xff1a; 若 i < k < j&#xff0c;當 k 為奇數時&#xff0c; A[k] > A[k1]&#xff0c;且當 k 為偶數時&#xff0c;A[k] < A[k1]&#xff1b; 或 若 i < k < j&…

spring boot源碼下載地址

github下載&#xff1a; https://github.com/spring-projects/spring-boot/tree/1.5.x git地址&#xff1a; https://github.com/spring-projects/spring-boot.git 因為項目中目前使用的就是spring boot 1.5.19版本&#xff0c;因此這里先研究spring boot 1.5版本源碼.轉載于:h…

java基礎學習——5、HashMap實現原理

一、HashMap的數據結構 數組的特點是&#xff1a;尋址容易&#xff0c;插入和刪除困難&#xff1b;而鏈表的特點是&#xff1a;尋址困難&#xff0c;插入和刪除容易。那么我們能不能綜合兩者的特性&#xff0c;做出一種尋址容易&#xff0c;插入刪除也容易的數據結構&#xff1…

看懂nfl定理需要什么知識_NFL球隊為什么不經常通過?

看懂nfl定理需要什么知識Debunking common NFL myths in an analytical study on the true value of passing the ball在關于傳球真實價值的分析研究中揭穿NFL常見神話 Background背景 Analytics are not used enough in the NFL. In a league with an abundance of money, i…

Docker初學者指南-如何創建您的第一個Docker應用程序

您是一名開發人員&#xff0c;并且想要開始使用Docker&#xff1f; 本文是為您準備的。 (You are a developer and you want to start with Docker? This article is made for you.) After a short introduction on what Docker is and why to use it, you will be able to cr…

mybatis if-else(寫法)

mybaits 中沒有else要用chose when otherwise 代替 范例一 <!--批量插入用戶--> <insert id"insertBusinessUserList" parameterType"java.util.List">insert into business_user (id , user_type , user_login )values<foreach collection…