索引 API

编辑

请参阅 移除映射类型

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

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

请求

编辑

PUT /<目标>/_doc/<_id>

POST /<目标>/_doc/

PUT /<目标>/_create/<_id>

POST /<目标>/_create/<_id>

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

前提条件

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

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

路径参数

编辑
<目标>

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

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

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

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

<_id>

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

以下请求格式需要此参数

  • PUT /<目标>/_doc/<_id>
  • PUT /<目标>/_create/<_id>
  • POST /<目标>/_create/<_id>

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

查询参数

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

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

如果请求的目标是数据流,则需要 createop_type。请参阅 向数据流添加文档

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

请求体

编辑
<字段>
(必需,字符串)请求体包含文档数据的 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(
    persistent={
        "action.auto_create_index": "my-index-000001,index10,-index1*,+ind*"
    },
)
print(resp)

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

resp2 = client.cluster.put_settings(
    persistent={
        "action.auto_create_index": "true"
    },
)
print(resp2)
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
const response = await client.cluster.putSettings({
  persistent: {
    "action.auto_create_index": "my-index-000001,index10,-index1*,+ind*",
  },
});
console.log(response);

const response1 = await client.cluster.putSettings({
  persistent: {
    "action.auto_create_index": "false",
  },
});
console.log(response1);

const response2 = await client.cluster.putSettings({
  persistent: {
    "action.auto_create_index": "true",
  },
});
console.log(response2);
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",
    document={
        "@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
const response = await client.index({
  index: "my-index-000001",
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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",
    document={
        "@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
const response = await client.index({
  index: "my-index-000001",
  routing: "kimchy",
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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_shardsall(或 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",
    document={
        "@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
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  timeout: "5m",
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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 的数值长整型值。

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

resp = client.index(
    index="my-index-000001",
    id="1",
    version="2",
    version_type="external",
    document={
        "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
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  version: 2,
  version_type: "external",
  document: {
    user: {
      id: "elkbee",
    },
  },
});
console.log(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",
    document={
        "@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
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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",
    document={
        "@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
const response = await client.create({
  index: "my-index-000001",
  id: 1,
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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",
    document={
        "@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
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  op_type: "create",
  document: {
    "@timestamp": "2099-11-15T13:12:00",
    message: "GET /search HTTP/1.1 200 1070000",
    user: {
      id: "kimchy",
    },
  },
});
console.log(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"
  }
}