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.mzph.cn/news/391894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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…

马尔科夫链蒙特卡洛_蒙特卡洛·马可夫链

马尔科夫链蒙特卡洛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…

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…

java基础学习——5、HashMap实现原理

一、HashMap的数据结构 数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构&#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…

29/07/2010 sunrise

** .. We can only appreciate the miracle of a sunrise if we have waited in the darkness .. 人们在黑暗中等待着,那是期盼着如同日出般的神迹出现 .. 附:27/07/2010 sunrise ** --- 31 July 改动转载于:https://www.cnblogs.com/orderedchaos/archi…

密度聚类dbscan_DBSCAN —基于密度的聚类方法的演练

密度聚类dbscanThe idea of having newer algorithms come into the picture doesn’t make the older ones ‘completely redundant’. British statistician, George E. P. Box had once quoted that, “All models are wrong, but some are useful”, meaning that no model…

嵌套路由

父组件不能用精准匹配,否则只组件路由无法展示 转载于:https://www.cnblogs.com/dianzan/p/11308146.html

从完整的新手到通过TensorFlow开发人员证书考试

I recently graduated with a bachelor’s degree in Civil Engineering and was all set to start with a Master’s degree in Transportation Engineering this fall. Unfortunately, my plans got pushed to the winter term because of COVID-19. So as of January this y…

【转】PHP面试题总结

PHP面试总结 PHP基础1:变量的传值与引用。 2:变量的类型转换和判断类型方法。 3:php运算符优先级,一般是写出运算符的运算结果。 4:PHP中函数传参,闭包,判断输出的echo,print是不是函…

移动平均线ma分析_使用动态移动平均线构建交互式库存量和价格分析图

移动平均线ma分析I decided to code out my own stock tracking chart despite a wide array of freely available tools that serve the same purpose. Why? Knowledge gain, it’s fun, and because I recognize that a simple project can generate many new ideas. Even t…

静态变数和非静态变数_统计资料:了解变数

静态变数和非静态变数Statistics 101: Understanding the different type of variables.统计101:了解变量的不同类型。 As we enter the latter part of the year 2020, it is safe to say that companies utilize data to assist in making business decisions. F…

Zabbix3.2安装

一、环境 OS: CentOS7.0.1406 Zabbix版本: Zabbix-3.2 下载地址: http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm MySQL版本: 5.6.37 MySQL: http://repo.mysql.com/mysql-community-release-el7-5.noarch.r…

Warensoft Unity3D通信库使用向导4-SQL SERVER访问组件使用说明

Warensoft Unity3D通信库使用向导4-SQL SERVER访问组件使用说明 (作者:warensoft,有问题请联系warensoft163.com) 在前一节《warensoft unity3d通信库使用向导3-建立WarensoftDataService》中已经说明如何配置Warensoft Data Service,从本节开始,将说明…

不知道输入何时停止_知道何时停止

不知道输入何时停止In predictive analytics, it can be a tricky thing to know when to stop.在预测分析中,知道何时停止可能是一件棘手的事情。 Unlike many of life’s activities, there’s no definitive finishing line, after which you can say “tick, I…

掌握大数据数据分析师吗?_要掌握您的数据吗? 这就是为什么您应该关心元数据的原因...

掌握大数据数据分析师吗?Either you are a data scientist, a data engineer, or someone enthusiastic about data, understanding your data is one thing you don’t want to overlook. We usually regard data as numbers, texts, or images, but data is more than that.…

docker在Centos上的安装

Centos6安装docker 系统:centos6.5 内核:3.10.107-1(已升级),docker对RHEL/Centos的最低内核支持是2.6.32-431,epel源的docker版本推荐内核为3.10版本。 内核升级可参考:https://www.jslink.org/linux/centos-kernel-u…

Lambda表达式的前世今生

Lambda 表达式 早在 C# 1.0 时,C#中就引入了委托(delegate)类型的概念。通过使用这个类型,我们可以将函数作为参数进行传递。在某种意义上,委托可理解为一种托管的强类型的函数指针。 通常情况下,使用委托来…