索引 API编辑

将 JSON 文档添加到指定的数据流或索引中,并使其可搜索。如果目标是索引,并且文档已存在,则请求会更新文档并增加其版本。

您不能使用索引 API 向数据流发送现有文档的更新请求。参见 通过查询更新数据流中的文档更新或删除支持索引中的文档.

请求编辑

PUT /<target>/_doc/<_id>

POST /<target>/_doc/

PUT /<target>/_create/<_id>

POST /<target>/_create/<_id>

您不能使用 PUT /<target>/_doc/<_id> 请求格式向数据流添加新文档。要指定文档 ID,请使用 PUT /<target>/_create/<_id> 格式。参见 向数据流添加文档.

先决条件编辑

  • 如果启用了 Elasticsearch 安全功能,则您必须对目标数据流、索引或索引别名具有以下 索引权限

    • 要使用 PUT /<target>/_doc/<_id> 请求格式添加或覆盖文档,您必须具有 createindexwrite 索引权限。
    • 要使用 POST /<target>/_doc/PUT /<target>/_create/<_id>POST /<target>/_create/<_id> 请求格式添加文档,您必须具有 create_doccreateindexwrite 索引权限。
    • 要使用索引 API 请求自动创建数据流或索引,您必须具有 auto_configurecreate_indexmanage 索引权限。
  • 自动数据流创建需要与启用了数据流的索引模板匹配。参见 设置数据流.

路径参数编辑

<target>

(必需,字符串) 要定位的数据流或索引的名称。

如果目标不存在,并且与 具有 data_stream 定义的索引模板 的名称或通配符 (*) 模式匹配,则此请求会创建数据流。参见 设置数据流.

如果目标不存在,并且与数据流模板不匹配,则此请求会创建索引。

您可以使用解析索引 API 检查现有目标。

<_id>

(可选,字符串) 文档的唯一标识符。

此参数对于以下请求格式是必需的

  • PUT /<target>/_doc/<_id>
  • PUT /<target>/_create/<_id>
  • POST /<target>/_create/<_id>

要自动生成文档 ID,请使用 POST /<target>/_doc/ 请求格式并省略此参数。

查询参数编辑

if_seq_no
(可选,整数) 仅当文档具有此序列号时才执行操作。参见 乐观并发控制.
if_primary_term
(可选,整数) 仅当文档具有此主项时才执行操作。参见 乐观并发控制.
op_type

(可选,枚举) 设置为 create 仅当文档不存在时才索引文档 (如果不存在则放入)。如果具有指定 _id 的文档已存在,则索引操作将失败。与使用 <index>/_create 端点相同。有效值:indexcreate。如果指定了文档 ID,则默认为 index。否则,默认为 create

如果请求定位数据流,则需要 op_typecreate。参见 向数据流添加文档.

pipeline
(可选,字符串) 要用于预处理传入文档的管道的 ID。如果索引指定了默认的摄取管道,则将值设置为 _none 会为该请求禁用默认的摄取管道。如果配置了最终管道,它将始终运行,无论此参数的值如何。
refresh
(可选,枚举) 如果为 true,则 Elasticsearch 会刷新受影响的分片,以使此操作对搜索可见,如果为 wait_for,则等待刷新以使此操作对搜索可见,如果为 false,则不执行任何刷新操作。有效值:truefalsewait_for。默认:false
routing
(可选,字符串) 用于将操作路由到特定分片的自定义值。
timeout

(可选,时间单位) 请求等待以下操作的期限

默认为 1m(一分钟)。这保证 Elasticsearch 至少等待超时时间才会失败。实际等待时间可能更长,尤其是在发生多次等待时。

version
(可选,整数) 用于并发控制的显式版本号。指定的版本必须与文档的当前版本匹配,才能使请求成功。
version_type
(可选,枚举) 特定的版本类型:externalexternal_gte
wait_for_active_shards

(可选,字符串) 在继续操作之前必须处于活动状态的分片副本数量。设置为 all 或任何正整数,直到索引中的分片总数 (number_of_replicas+1)。默认:1,主分片。

参见 活动分片.

require_alias
(可选,布尔值) 如果为 true,则目标必须是 索引别名。默认为 false

请求主体编辑

<field>
(必需,字符串) 请求主体包含文档数据的 JSON 源。

响应主体编辑

_shards
提供有关索引操作的复制过程的信息。
_shards.total
指示索引操作应在多少个分片副本(主分片和副本分片)上执行。
_shards.successful

指示索引操作成功执行的分片副本数量。当索引操作成功时,successful 至少为 1。

当索引操作成功返回时,副本分片可能并不都已启动——默认情况下,只需要主分片。设置 wait_for_active_shards 可以更改此默认行为。参见 活动分片.

_shards.failed
一个数组,在索引操作在副本分片上失败的情况下包含与复制相关的错误。0 表示没有失败。
_index
添加文档的索引的名称。
_type
文档类型。Elasticsearch 索引现在支持单个文档类型,_doc
_id
添加文档的唯一标识符。
_version
文档版本。每次更新文档时都会递增。
_seq_no
为索引操作分配给文档的序列号。序列号用于确保旧版本的文档不会覆盖新版本。请参阅 乐观并发控制
_primary_term
为索引操作分配给文档的主项。请参阅 乐观并发控制
result
索引操作的结果,createdupdated

描述编辑

您可以使用 _doc_create 资源索引新的 JSON 文档。使用 _create 可确保仅在文档不存在时才对其进行索引。要更新现有文档,您必须使用 _doc 资源。

自动创建数据流和索引编辑

如果请求的目标不存在且与 具有 data_stream 定义的索引模板匹配,则索引操作会自动创建数据流。请参阅 设置数据流

如果目标不存在且与数据流模板不匹配,则操作会自动创建索引并应用任何匹配的 索引模板

Elasticsearch 包含多个内置索引模板。为了避免与这些模板发生命名冲突,请参阅 避免索引模式冲突

如果不存在映射,则索引操作会创建动态映射。默认情况下,如果需要,新的字段和对象会自动添加到映射中。有关字段映射的更多信息,请参阅 映射更新映射 API。

自动索引创建由 action.auto_create_index 设置控制。此设置默认为 true,允许自动创建任何索引。您可以修改此设置以明确允许或阻止与指定模式匹配的索引的自动创建,或者将其设置为 false 以完全禁用自动索引创建。指定要允许的模式的逗号分隔列表,或在每个模式前加 +- 以指示是否应允许或阻止它。当指定列表时,默认行为是禁止。

action.auto_create_index 设置仅影响索引的自动创建。它不影响数据流的创建。

resp = client.cluster.put_settings(
    body={
        "persistent": {
            "action.auto_create_index": "my-index-000001,index10,-index1*,+ind*"
        }
    },
)
print(resp)

resp = client.cluster.put_settings(
    body={"persistent": {"action.auto_create_index": "false"}},
)
print(resp)

resp = client.cluster.put_settings(
    body={"persistent": {"action.auto_create_index": "true"}},
)
print(resp)
response = client.cluster.put_settings(
  body: {
    persistent: {
      'action.auto_create_index' => 'my-index-000001,index10,-index1*,+ind*'
    }
  }
)
puts response

response = client.cluster.put_settings(
  body: {
    persistent: {
      'action.auto_create_index' => 'false'
    }
  }
)
puts response

response = client.cluster.put_settings(
  body: {
    persistent: {
      'action.auto_create_index' => 'true'
    }
  }
)
puts response
PUT _cluster/settings
{
  "persistent": {
    "action.auto_create_index": "my-index-000001,index10,-index1*,+ind*" 
  }
}

PUT _cluster/settings
{
  "persistent": {
    "action.auto_create_index": "false" 
  }
}

PUT _cluster/settings
{
  "persistent": {
    "action.auto_create_index": "true" 
  }
}

允许自动创建名为 my-index-000001index10 的索引,阻止创建与模式 index1* 匹配的索引,并允许创建与 ind* 模式匹配的任何其他索引。模式按指定的顺序匹配。

完全禁用自动索引创建。

允许自动创建任何索引。这是默认设置。

如果不存在则放入编辑

您可以通过使用 _create 资源或将 op_type 参数设置为 create 来强制执行创建操作。在这种情况下,如果索引中已存在具有指定 ID 的文档,则索引操作将失败。

自动创建文档 ID编辑

使用 POST /<target>/_doc/ 请求格式时,op_type 会自动设置为 create,并且索引操作会为文档生成一个唯一的 ID。

resp = client.index(
    index="my-index-000001",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
POST my-index-000001/_doc/
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}

API 返回以下结果

{
  "_shards": {
    "total": 2,
    "failed": 0,
    "successful": 2
  },
  "_index": "my-index-000001",
  "_id": "W0tpsmIBdwcYyG50zbta",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "result": "created"
}
乐观并发控制编辑

索引操作可以设置为条件操作,并且仅在对文档的最后修改被分配了 if_seq_noif_primary_term 参数指定的序列号和主项时才执行。如果检测到不匹配,则操作将导致 VersionConflictException 和状态代码 409。有关更多详细信息,请参阅 乐观并发控制

路由编辑

默认情况下,分片放置(或 routing)通过使用文档 ID 值的哈希来控制。为了更明确地控制,可以使用 routing 参数在每个操作的基础上直接指定馈送到路由器使用的哈希函数的值。例如

resp = client.index(
    index="my-index-000001",
    routing="kimchy",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  routing: 'kimchy',
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
POST my-index-000001/_doc?routing=kimchy
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}

在此示例中,文档根据提供的 routing 参数:“kimchy”路由到分片。

在设置显式映射时,您还可以使用 _routing 字段来指示索引操作从文档本身提取路由值。这确实会带来额外的文档解析传递的(非常小的)成本。如果定义了 _routing 映射并将其设置为 required,则如果未提供或提取路由值,则索引操作将失败。

数据流不支持自定义路由,除非它们是在模板中启用了 allow_custom_routing 设置的情况下创建的。

分布式编辑

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

活动分片编辑

为了提高对系统的写入的弹性,可以配置索引操作以等待一定数量的活动分片副本,然后再继续执行操作。如果所需的活动分片副本数量不可用,则写入操作必须等待并重试,直到所需的副本启动或超时。默认情况下,写入操作仅在主分片处于活动状态后才继续执行(即 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
  }
}
刷新编辑

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

空操作更新编辑

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

关于何时空操作更新不可接受没有硬性规定。它结合了许多因素,例如数据源发送实际为空操作的更新的频率以及 Elasticsearch 在接收更新的分片上运行的每秒查询次数。

超时编辑

执行索引操作时,分配执行索引操作的主分片可能不可用。导致这种情况的一些原因可能是主分片当前正在从网关恢复或正在进行重新定位。默认情况下,索引操作将等待主分片最多 1 分钟才能变为可用,然后才会失败并返回错误。可以使用 timeout 参数显式指定等待时间。以下是如何将其设置为 5 分钟的示例

resp = client.index(
    index="my-index-000001",
    id="1",
    timeout="5m",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  timeout: '5m',
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
PUT my-index-000001/_doc/1?timeout=5m
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}
版本控制编辑

每个索引文档都将获得一个版本号。默认情况下,使用从 1 开始的内部版本控制,并在每次更新(包括删除)时递增。可选地,版本号可以设置为外部值(例如,如果在数据库中维护)。要启用此功能,应将 version_type 设置为 external。提供的值必须是大于或等于 0 且小于约 9.2e+18 的数字长整型值。

使用外部版本类型时,系统会检查传递给索引请求的版本号是否大于当前存储的文档的版本。如果为真,则将索引文档并使用新的版本号。如果提供的值小于或等于存储的文档的版本号,则会发生版本冲突,索引操作将失败。例如

resp = client.index(
    index="my-index-000001",
    id="1",
    version="2",
    version_type="external",
    body={"user": {"id": "elkbee"}},
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  version: 2,
  version_type: 'external',
  body: {
    user: {
      id: 'elkbee'
    }
  }
)
puts response
PUT my-index-000001/_doc/1?version=2&version_type=external
{
  "user": {
    "id": "elkbee"
  }
}

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

在前面的示例中,操作将成功,因为提供的版本 2 高于当前文档版本 1。如果文档已更新且其版本已设置为 2 或更高,则索引命令将失败并导致冲突(409 http 状态代码)。

一个很好的副作用是,无需维护对作为对源数据库更改的结果而执行的异步索引操作的严格排序,只要使用源数据库的版本号即可。即使使用来自数据库的数据更新 Elasticsearch 索引的简单情况,如果使用外部版本控制,也会变得更简单,因为如果索引操作由于任何原因而无序到达,则只会使用最新版本。

版本类型编辑

除了 external 版本类型之外,Elasticsearch 还支持其他类型以用于特定用例

externalexternal_gt
仅当给定版本严格高于存储的文档的版本 不存在现有文档时,才索引文档。给定版本将用作新版本,并将与新文档一起存储。提供的版本必须是非负长整型数。
external_gte
仅当给定版本 等于或高于存储的文档的版本时,才索引文档。如果不存在现有文档,操作也将成功。给定版本将用作新版本,并将与新文档一起存储。提供的版本必须是非负长整型数。

external_gte 版本类型适用于特殊用例,应谨慎使用。如果使用不当,会导致数据丢失。还有另一个选项 force,它已弃用,因为它会导致主分片和副本分片发生分歧。

示例编辑

将 JSON 文档插入 my-index-000001 索引中,其 _id 为 1

resp = client.index(
    index="my-index-000001",
    id="1",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
PUT my-index-000001/_doc/1
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}

API 返回以下结果

{
  "_shards": {
    "total": 2,
    "failed": 0,
    "successful": 2
  },
  "_index": "my-index-000001",
  "_id": "1",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "result": "created"
}

使用 _create 资源将文档索引到 my-index-000001 索引中,前提是该 ID 不存在。

resp = client.create(
    index="my-index-000001",
    id="1",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.create(
  index: 'my-index-000001',
  id: 1,
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
PUT my-index-000001/_create/1
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}

op_type 参数设置为 create,将文档索引到 my-index-000001 索引中,前提是该 ID 不存在。

resp = client.index(
    index="my-index-000001",
    id="1",
    op_type="create",
    body={
        "@timestamp": "2099-11-15T13:12:00",
        "message": "GET /search HTTP/1.1 200 1070000",
        "user": {"id": "kimchy"},
    },
)
print(resp)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  op_type: 'create',
  body: {
    "@timestamp": '2099-11-15T13:12:00',
    message: 'GET /search HTTP/1.1 200 1070000',
    user: {
      id: 'kimchy'
    }
  }
)
puts response
PUT my-index-000001/_doc/1?op_type=create
{
  "@timestamp": "2099-11-15T13:12:00",
  "message": "GET /search HTTP/1.1 200 1070000",
  "user": {
    "id": "kimchy"
  }
}