Index API

index API在特定索引中添加或更新JSON类型化文档,使其可搜索,下面的示例将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设置的总碎片,successful将等于启动的碎片数(主碎片加副本),如果没有失败,则failed为0。

自动创建索引

如果之前没有创建索引,则索引操作将自动创建索引(查看用于手动创建索引的create index API),并且如果还没有创建特定类型,还会自动为该类型创建动态类型映射(请参阅put mapping API以手动创建类型映射)。

映射本身非常灵活,并且没有模式,新的字段和对象将自动添加到指定类型的映射定义中,查看映射部分以获得关于映射定义的更多信息。

可以通过在所有节点的配置文件中设置action.auto_create_indexfalse禁用自动索引创建,可以通过将index.mapper.dynamic为每个索引设置为false来禁用自动映射创建。

自动索引创建可以包括基于白/黑名单列表的模式,例如,将action.auto_create_index设置为+aaa*-bbb*+ccc*-*+表示允许,-表示不允许)。

版本控制

每个索引的文档都有一个版本号,关联的version作为对index API请求的响应的一部分返回,当指定version参数时,index API可选的允许乐观锁并发控制,这将控制要对其执行操作的文档的版本。版本控制用例的一个很好的例子是执行事务读 - 然后更新,指定一个从最初读取的文档中的version,可以确保在此期间没有发生任何更改(当读是为了更新时,建议将preference设置为_primary),例如:

PUT twitter/_doc/1?version=2
{
    "message" : "elasticsearch now has versioning support, double cool!"
}

注意:版本控制是完全实时的,并且不受搜索操作的接近实时方面的影响,如果没有提供版本,则在不进行任何版本检查的情况下执行操作。

默认情况下,内部版本控制从1开始,每次更新时递增,包括删除。可选地,版本号可以用外部值进行补充(例如,如果维护在数据库中),要启用该功能,应该将version_type设置为external。提供的值必须是一个数值,大于或等于0的long值,并小于9.2e+18在使用外部版本类型时,系统检查传递给索引请求的版本号是否大于当前存储文档的版本号,而不是检查匹配的版本号,如果为true,则对文档进行索引并使用新的版本号,如果提供的值小于或等于存储文档的版本号,将发生版本冲突,索引操作将失败。

外部版本控制支持将值0作为有效的版本号,这允许版本与版本号是从0开始而不是从1开始的外部版本控制系统同步。它的副作用是,版本号为0的文档既不能使用Update By Query API进行更新,也不能使用Delete By Query API进行删除,只要它们的版本号为0。

一个好的副作用是,只要使用了源数据库的版本号,就不需要维护由于更改源数据库而执行的异步索引操作的严格顺序。如果使用外部版本控制,那么即使使用数据库中的数据更新Elasticsearch索引的简单情况也会得到简化,因为如果索引操作由于某种原因出现故障,则只使用最新版本。

版本类型

除了上面介绍的internalexternal版本类型之外,Elasticsearch还为特定的用例支持其他类型,下面是不同版本类型及其语义的概述。

internal

  • 只有当给定版本与存储文档的版本相同时,才对文档进行索引。

externalexternal_gt

  • 只有在给定版本严格地高于存储文档的版本没有现有文档时,才对文档进行索引,给定的版本将作为新版本使用,并与新文档一起存储,提供的版本必须是非负的long数字。

external_gte

  • 只有在给定版本等于或高于存储文档版本的情况下,才对文档进行索引,如果没有现有文档,操作也会成功,给定的版本将作为新版本使用,并与新文档一起存储,提供的版本必须是非负的long数字。
external_gte版本类型用于特殊的用例,应该小心使用,如果使用不当,可能导致数据丢失,还有另一个选项,force,它被废弃了,因为它会导致主碎片和副本碎片分离。

操作类型

索引操作还接受op_type,可用于强制一个create操作,允许“put-if-absent”的行为,使用create时,如果该id文档已经存在于索引中,则索引操作将失败。

下面是一个使用op_type参数的示例:

PUT twitter/_doc/1?op_type=create
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

指定create的另一个选项是使用以下uri:

PUT twitter/_doc/1/_create
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

自动生成ID

可以在不指定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"
}

路由

默认情况下,碎片放置(或routing)是通过使用文档的id值的hash来控制的,为了实现更显式的控制,可以使用routing参数直接在每个操作的基础上指定路由器使用的hash函数的值,例如:

POST twitter/_doc?routing=kimchy
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

在上面的示例中,“_doc”文档根据提供的routing参数“kimchy”被路由到一个碎片。

在设置显式映射时,可以选择使用_routing字段指导索引操作,从文档本身提取路由值,这确实需要额外的文档解析传递的成本(非常低),如果定义了_routing映射并设置为required,如果没有提供或提取到路由值,索引操作将失败。

分发

索引操作根据其路由(请参阅上面的路由部分)定向到主碎片,并在包含此碎片的实际节点上执行,主碎片完成操作后,如果需要,更新将分发给合适的副本。

等待活动碎片

为了提高对系统的写操作的弹性,可以将索引操作配置为在继续操作之前等待一定数量的活动碎片副本,如果必需的活动碎片副本数量不可用,那么写操作必须等待并重试,直到必要的碎片副本启动或超时。默认情况下,写操作只等待主碎片处于活动状态后再继续(即wait_for_active_shards=1),通过设置index.write.wait_for_active_shards,可以在索引设置中动态覆盖此默认值,要更改每个操作的这种行为,可以使用wait_for_active_shards请求参数。

有效值是all或索引中每个碎片中配置的副本总数的任意正整数(即number_of_replicas+1),指定一个负数或一个大于碎片副本数量的数字会抛出错误。

例如,假设我们有一个由三个节点组成的集群,ABC,我们创建一个索引,index将副本的数量设置为3(结果是4个碎片副本,比节点多一个副本)。如果我们尝试索引操作,默认情况下,操作只会在继续之前确保每个碎片的主副本可用,这意味着,即使BC宕机,并且A托管主碎片副本,索引操作仍然只处理数据的一个副本。如果将wait_for_active_shards设置为3(所有3个节点都已启动),那么在继续之前,索引操作将需要3个活动碎片副本,这一要求应该得到满足,因为集群中有3个活动节点,每个节点都持有碎片的副本。但是,如果我们将wait_for_active_shards设置为all(或4,这是相同的),索引操作将不会继续,因为索引中没有每个活动碎片的所有4个副本,除非集群中出现一个新节点来承载碎片的第四个副本,否则操作将超时。

需要注意的是,这个设置大大减少了写操作不写入到所需碎片副本数量的机会,但它并没有完全排除这种可能性,因为这种检查发生在写操作开始之前,一旦写操作开始,复制仍然可能在任何数量的碎片副本上失败,但在主副本上仍然成功,写操作响应的_shards部分显示复制成功/失败的碎片副本的数量。

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    }
}

刷新

控制何时该请求所做的更改对搜索可见,参阅?refresh

无操作的更新

在使用索引api更新文档时,即使文档没有更改,也总是会创建文档的新版本,如果这是不可接受的,使用_update api将detect_noop设置为true,这个选项在索引api上不可用,因为索引api不会获取旧源,并且无法将其与新源进行比较。

对于无操作的更新什么时候不可接受,并没有硬性规定,它是许多因素的组合,比如数据源发送实际上是无操作的更新的频率,以及每秒钟Elasticsearch在正在接收更新的碎片上运行多少查询。

超时

当执行索引操作时,分配给执行索引操作的主碎片可能不可用,其中的一些原因可能是主碎片正在从网关中恢复或正在经历重定位。默认情况下,索引操作将等待主碎片变得可用1分钟,然后失败并响应错误,可以使用timeout参数显式地指定它的等待时间,这里有一个将其设置为5分钟的例子:

PUT twitter/_doc/1?timeout=5m
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}

上一篇:读和写文档

博弈
2.5k 声望1.5k 粉丝

态度决定一切