Single document APIs
Multi-document APIs
所有CRUD api都是单索引api。索引参数接受单个索引名,或指向单个索引的别名。
1、Index API
index API 可以添加或者更新特定索引的文档,并使其可搜索。下面的例子插入一个 json 格式的文档到 "twitter" 索引的 "_doc" 类型中,并指定 id 为1:
PUT twitter/_doc/1
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
返回结果:
{
"_shards" : {
"total" : 2,
"failed" : 0,
"successful" : 2
},
"_index" : "twitter",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"result" : "created"
}
_shards
字段提供索引操作复制过程的处理信息:
-
total
:表示索引操作应该在多少个分片上(包括副本分片和主分片)执行 -
successful
:表示成功执行索引操作的分片数量 -
failed
:表示执行索引操作失败的分片的数组。
successful
大于等于1就认为索引操作成功,因为最少有一个分片可以查到数据了。
当索引操作返回时,复制分片有可能还没有完全启用(默认,主分片是必须启用的,但这个行为可以修改)。
total
字段等于复制分片数(number_of_replicas + 1
),successful
等于成功执行索引操作的分片数(包括主分片和副本分片,因为副本分片所在的节点还不一定可用,所以有可能和total
不等)。如果没有任何错误发生,failed
的值是0
1.1 自动创建索引(Automatic Index Creation)
如果索引不存在,则 index 操作会自动创建该索引(查阅create index API了解手动创建索引)并作用到已配置的任何索引模板中。
索引操作还会为指定的类型创建动态类型映射(如果尚不存在)。默认情况下,如果需要,新字段和对象将自动添加到指定类型的mapping 定义中。有关 mapping 定义的更多信息,请查看 mapping 部分;有关手动更新 mapping 类型的信息,请查看 put mapping API。
自动索引创建由action.auto_create_index
设置控制。此设置默认为 true
,表示始终自动创建索引。将它设置为false
可以禁用自动创建索引。
自动创建索引可以使用白/黑名单列表。例如:设置 action.auto_create_index = +aaa*,-bbb*,+ccc*,-*
(+
代表允许,-
代表禁止)
#只允许自动创建名为twitter,index10的索引,没有其他索引匹配index1 *,以及任何其他匹配ind *的索引。模式按照给定的顺序进行匹配。
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "twitter,index10,-index1*,+ind*"
}
}
#完全禁用索引的自动创建。
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "false"
}
}
#允许使用任何名称自动创建索引。这是默认值。
PUT _cluster/settings
{
"persistent": {
"action.auto_create_index": "true"
}
}
1.2 操作类型(Operation Type)
index 操作可以接受一个op_type
参数,它可以用来强制指定创建操作。允许put-if-absent
操作。当指定op_type=create
时,如果索引中已存在该 id 的文档,则索引操作将失败。下面举一个使用 op_type
参数的例子:
PUT twitter/_doc/1?op_type=create
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
另一种方式:
PUT twitter/_doc/1/_create
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
1.3 自动生成id(Automatic ID Generation)
没有指定 id 的索引操作会自动生成 id,除此之外,op_type
会被默认赋值create
。举个例子(注意使用的是POST
而不是PUT
):
POST twitter/_doc/
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
返回结果:
{
"_shards" : {
"total" : 2,
"failed" : 0,
"successful" : 2
},
"_index" : "twitter",
"_type" : "_doc",
"_id" : "W0tpsmIBdwcYyG50zbta",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"result": "created"
}
1.4 乐观锁(Optimistic concurrency control)
index 操作可以是有条件的,只有在为文档的最后一次修改分配了if_seq_no
和 if_primary_term
参数时才能执行索引操作。如果执行时这两个参数不匹配,则操作将导致VersionConflictException
的异常和状态代码409
的错误。有关详细信息,请参阅乐观锁。
每次成功进行写操作后,该文档的序列号(_seq_no)就为自增,文档刚创建的时 _seq_no=0
假设创建文档后又对文档进行了3次 index
1.5 路由(Routing)
默认情况下,通过使用文档ID值的哈希值来控制分片的位置。如果想要更显式的控制,你可以显式指定routing
参数,使用自定义的被hash的值:
POST twitter/_doc?routing=kimchy
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
对于上述例子,上面的文档被路由到与hash(kimchy
)对应的分片中
当显式指定映射时,_routing
参数可以使用自身的字段值作为路由值来指导索引操作。这确实需要额外的文档解析过程(非常小的)开销。如果在映射中指定了_routing
并将其设置为required
,当没有给定routing
参数或者映射_routing
字段对应的文档字段值不可用时,该索引操作将会失败。
1.6 分布式(Distributed)
索引操作基于路由值(查看上述的routing章节)定向到对应的主分片,并在包含该分片的实际节点上执行操作。当主分片完成索引操作后,如果需要,更新将分发到适用的副本。
1.7 等待活跃分片(Wait For Active Shards)
为了改善写操作的健壮性,索引操作可以设置成等待具有指定数量的活跃分片数时才执行。如果所需数量的活动分片副本不可用,则写入操作必须等待并重试,直到所需活跃分片副本足够或者发生超时。默认情况下,写入操作仅在继续之前等待主分片处于活动状态(即wait_for_active_shards=1
,1代表主分片的意思)。这个默认值可以用过设置index.write.wait_for_active_shards
在索引设置中被动态覆盖。可以在请求参数中指定wait_for_active_shards
改变每个请求的此行为的操作。
有效值是all
和正整数,最多为索引中每个分片配置的副本总数(即number_of_replicas + 1
)。指定负数或者大于最大值的数都会报错。
例如,假如我们有一个3个节点的集群,A
,B
,C
,每个节点都有3个副本分片(即每个文档都会被索引到4个分片,此时分片数量比节点数还多一个,即有一个副本分片处于不可用的状态)。如果我们尝试执行索引操作,在执行之前,该操作默认会确保主分片在继续操作之前是否可用。这意味着,即使B,C都宕机了,A主机拥有主分片,索引操作依然可以执行,但只有一份数据(主分片,副本分片不可用)。如果把wait_for_active_shards
设置为3,并且三个节点都可以用,就那么索引操作将需要3个活动的shard副本才能继续,这一要求应该满足,因为群集中有3个活动的节点,每个节点都保存一个shard副本。 然而如果我们将wait_for_active_shards
指定为all
或者4,则索引操作将不会被执行,因为我们没有4个活跃的节点。这个操作将会超时,除非集群中出现一个新节点来承载第四个shard副本。
需要注意的是,此配置可以极大的降低了写操作只写到主分片但没有写到副本分片的可能性。但它并不能完全消除这种可能性,因为副本分片有可能在执行前是可用的,但在索引执行过程中不可用。_shards
字段说明了索引在各个分片执行的情况。
{
"_shards" : {
"total" : 2,
"failed" : 0,
"successful" : 2
}
}
1.8 刷新(refresh)
如果当前操作是修改操作,可以通过refresh强制要求修改后马上可以被搜索结果(因为接近实时有一定的延迟)。查阅 refresh。即该参数控制当有更改时在请求结果中是否立即可见。
1.9 空操作(Noop Updates)
当使用index API更新文档时,即使文档没有改变也会创建一个新的文档。如果不想创建新的文档,可以使用_update
API 并且指定参数detect_noop=true
.这个选项不能用于index API,因为index API无法获取旧的文档,并且无法将其与新文档进行比较。
并不是硬性规定你不接受空操作。这要结合多个因素。例如,数据源发送实际为空操作的频率(频率高的话应使用空操作避免不必要的索引)以及在elasticsearch在接收更新时每秒在shard上运行的查询数。(空操作,每次都要读旧数据,影响查询性能)。
1.10 超时(Timeout)
主分片执行索引操作时有可能会失败,可能的原因是主分片当前正在从网关恢复或者主分片正在进行迁移。默认情况下,索引操作会等待1分钟,如果主分片还是不可用就会报错。你可以在index API 中指定 timeout
参数。下面例子把timeout
设置为5分钟:
PUT twitter/_doc/1?timeout=5m
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
1.11 版本(Versioning)
每个被索引的文档都有一个版本号,index API 会在响应结果中返回这个版本号。默认情况下,内部的版本号是以1开始,并且每次更新和删除操作都会递增1。版本号也可以由外部提供(例如,在数据库中维护版本号),要启用此功能,需要将version_type
设置为external
。这个值必须是大于或者等于0
,且少于约9.2e+18
的数字。当使用外部的版本号比现有的版本号小时,该索引操作会失败。
如果在索引文档的时候指定版本号,该操作将会使用乐观锁(只要指定version参数就会使用乐观锁,使用内部版本号时会检查version参数和文档的version值是否一致,如果不一致则拒绝执行,一致则直接加1;使用外部版本号时会检查version参数是否比文档version值大,如果小于文档的version值就执行失败,否则该文档将使用指定的version参数作为版本号)。
PUT twitter/_doc/1?version=2&version_type=external
{
"message" : "elasticsearch now has versioning support, double cool!"
}
注意:版本控制是完全实时的,不受搜索操作的接近实时影响。如果未提供任何版本,则执行该操作而不进行任何版本检查。
由于提供的版本2高于当前文档版本1,因此上例操作将成功。如果文档已更新且其版本号为2或更高,则上例操作将失败并导致冲突(409 http状态代码)。
elasticsearch索引使用默认的版本时,用户不需要维护由于数据更改而执行的异步索引操作造成的索引更改。如果使用外部版本控制,即使使用数据库中的数据更新elasticsearch索引的情况也很简单,如果由于某些索引操作不正常,只会使用最新版本。
1.12 版本号类型(Version types)
接下来解释一下上面的内部和外部版本类型。elasticsearch也支持其他的用户自定义类型版本,这里介绍一下不同版本类型:
internal
只有指定的version同已经存在的文件version一样时才进行索引。
在6.7.0中弃用。请改用if_seq_no和if_primary_term。有关更多详细信息,请参阅乐观锁。
external
或 external_gt
只有指定的version参数高于已经存在的文档的version是,或不存在指定的version的文档时才进行索引。version参数将会用作新version使用,并将与新文档保持一致。且version参数必须是非负数。
external_gte
只有指定的version参数大于高于已经存在的文档的version时,或不存在指定的version的文档时才进行索引。version参数将会用作新version使用,并将与新文档保持一致。且version参数必须是非负数。
注意:
external_gte
版本类型是用于特殊场景的,需要小心使用。如果使用不当会丢失数据。还有另一个选项force
,它被弃用,因为它可能导致主分片和副本分片发散。