Index API

时间:2022-09-12 15:22:08

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"
}

返回结果如下:

{
"_index": "twitter",
"_type": "_doc",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

_shards头提供关于索引操作的复制过程的信息。

  • total - 表示执行索引操作的分片副本(主和副本分片)的数量。
  • successful - 表示索引操作成功的分片数量。
  • failed - 在副本分片上的索引操作失败的情况下,包含复制相关错误的数组。

在successful至少为1的情况下,索引操作才会成功。

当索引操作成功返回时(默认情况下,只需要主分片,但可以更改此行为),副本分片可能不会都启动。 在这种情况下,总数将等于number_of_replicas设置的总分片数,成功数将等于启动的分片数(primary + replicas)。 如果没有失败,失败将为0。

自动创建索引

如果之前没有创建索引,索引操作会自动创建一个索引(查看create index API了解如何手动创建索引)。还会为指定类型自动创建(查看put mapping API了解如何手动创建类型映射)一个动态类型映射(如果尚未创建的话)。

映射本身非常灵活并且无模式(schema-free)。新的字段和对象将自动添加到指定类型的映射定义中。查看映射部分以获取更多关于映射定义的信息。
自动索引创建可以通过在所有节点的配置文件中设置 action.auto_create_index=false 来禁用。设置 index.mapper.dynamic=false可以禁用自动创建映射。

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

版本控制

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

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

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

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

外部版本控制支持将值0作为有效的版本号。 这允许版本与外部版本控制系统同步(比如版本号从0开始而不是1的系统)。坏处是版本号等于零的文档不能使用Update-By-Query API更新,也不能使用Delete By Query API进行删除。

好处是只要使用源数据库的版本号,就不需要因源数据库更改而执行的异步索引操作进行严格排序。 如果使用外部版本控制,即使是使用数据库中的数据更新Elasticsearch索引也会得到简化,因为如果索引操作出现故障,则只会使用最新版本。

版本类型

上面已经解释了internal & external 版本类型,Elasticsearch还支持针对特定用例的其他类型。以下是不同版本类型及其语义的概述。
internal:如果给定版本与存储文档的版本相同,则索引文档。
external or external_gt:如果给定版本严格高于存储文档的版本或者文档不存在,则索引文档。 给定的版本将用作新版本,并将与新文档一起存储。 提供的版本必须是非负数长整数。
external_gte:如果给定版本等于或高于存储文档的版本,则索引文档。 如果文档不存在,操作也会成功。 给定的版本将用作新版本,并将与新文档一起存储。 提供的版本必须是非负数长整数。
注:external_gte版本类型只适用于特殊用途,应谨慎使用。 如果使用不当,可能会导致数据丢失。 还有另一个选项force,由于它可能导致主分片和副本分片不一致,因此不推荐使用。

操作类型

索引操作还接受可用于强制执行创建操作的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"
}

也可以像下面这样指定create:

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"
}

结果如下:

{
"_index": "twitter",
"_type": "_doc",
"_id": "gplwqWIB8vjrkQCAPbbJ",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

路由

默认情况下,分片放置或路由通过文档的id值的hash进行控制。 为了更明确的控制,路由使用的哈希函数中引入的值可以使用路由参数直接指定。 例如:

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

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

设置显式映射时,可以选择使用_routing字段来指示索引操作从文档本身提取路由值。 这会额外增加文档解析开销,不过成本非常小。 如果_routing映射被定义并被设置为必需的,那么如果路由值未提供或未提取到路由值,则索引操作将失败。

分步式

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

等待活动分片

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

有效值为全部或任何正整数,直到索引中每个分片的配置副本总数(即number_of_replicas + 1)。指定负值或大于分片数量的数字将引发错误。

例如,假设我们有一个由三个节点A,B和C组成的集群,并且我们创建了一个索引index,其副本数设置为3(导致4个分片副本,比节点多一个副本)。如果我们尝试进行索引操作:
1、默认情况下,操作只会确保每个分片的主分片可用,然后才能继续。这意味着,即使B和C发生故障,并且A托管了主分片副本,索引操作仍然会继续执行这唯一的一个数据副本。
2、如果请求中的wait_for_active_shards设置为3(并且所有3个节点都在运行),那么索引操作在继续之前需要3个活动分片副本,满足要求,因为集群中有3个活动节点,每个节点持有分片的副本。
3、如果我们将wait_for_active_shards设置为all(或者4也一样),则索引操作将不会继续,因为我们没有在索引中激活每个分片的所有4个副本。该操作将超时,除非在集群中引入新节点来托管分片的第四个副本。
值得注意的是,这种设置大大降低了写操作不写入所需数量的分片副本的可能性,但它并不能完全消除这种可能性,因为在写操作开始之前就会发生这种检查。 一旦写入操作正在进行,复制仍然有可能在任意数量的分片副本上失败,但仍然可以在主分片上成功。 写操作响应的_shards部分会显示复制成功/失败的分片副本的数量。

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

刷新

控制此请求所做的更改对搜索是否可见。 请参阅刷新

Noop Updates

使用索引api更新文档时,即使文档未更改,也始终创建新版本的文档。 如果不想这样,可以使用_update api,把detect_noop设置为true。 这个选项在索引api上不可用,因为索引api没有获取旧的数据,也无法将它与新的数据进行比较。

关于Noop Updates何时不可接受,并没有一条硬性规定。 这是多种因素的结合,例如数据源发送更新的频率实际上是noops,以及Elasticsearch每秒接收更新时在分片上运行的查询数量。

Timeout

执行索引操作时,分配用于执行索引操作的主分片可能不可用。 造成这种情况的一些原因可能是主分片正在从网关恢复或正在进行迁移。 默认情况下,索引操作将在主分片上等待最多1分钟,然后如果失败则响应并显示错误。 timeout参数可用于显式指定它等待的时间。 以下是将其设置为5分钟的示例:

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

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html