Link Search Menu Expand Document Documentation Menu

管理索引

您可以使用 OpenSearch REST API 索引数据。存在两种 API:索引 API 和 _bulk API。

对于新数据递增到达的情况(例如,小型企业的客户订单),您可以使用索引 API 在文档到达时单独添加它们。对于数据流不那么频繁的情况(例如,营销网站的每周更新),您可能更倾向于生成一个文件并将其发送到 _bulk API。对于大量文档,将请求捆绑在一起并使用 _bulk API 可以提供卓越的性能。但是,如果您的文档非常庞大,您可能需要单独索引它们。

索引文档时,文档 _id 的大小必须小于或等于 512 字节。

索引简介

在搜索数据之前,您必须对其进行索引。索引是搜索引擎组织数据以实现快速检索的方法。生成的结构被称为索引,恰如其分。

在 OpenSearch 中,数据的基本单位是 JSON 文档。在索引中,OpenSearch 使用唯一 ID 标识每个文档。

索引 API 的请求示例如下:

PUT <index>/_doc/<id>
{ "A JSON": "document" }

_bulk API 的请求略有不同,因为您在批量数据中指定了索引和 ID。

POST _bulk
{ "index": { "_index": "<index>", "_id": "<id>" } }
{ "A JSON": "document" }

批量数据必须符合特定格式,该格式要求每行(包括最后一行)末尾都有一个换行符 (\n)。这是基本格式:

Action and metadata\n
Optional document\n
Action and metadata\n
Optional document\n

文档是可选的,因为 delete 操作不需要文档。其他操作(indexcreateupdate)都需要文档。如果您特别希望在文档已存在时操作失败,请使用 create 操作而不是 index 操作。

要使用 curl 命令索引批量数据,请导航到文件保存的文件夹并运行以下命令:

curl -H "Content-Type: application/x-ndjson" -POST https://:9200/data/_bulk -u 'admin:admin' --insecure --data-binary "@data.json"

如果 _bulk API 中的任何一个操作失败,OpenSearch 会继续执行其他操作。检查响应中的 items 数组以找出问题所在。items 数组中的条目与请求中指定的操作顺序相同。

当您将文档添加到尚不存在的索引时,OpenSearch 会自动创建该索引。如果您在请求中未指定 ID,它还会自动生成一个 ID。这个简单的示例会自动创建 movies 索引,索引文档,并为其分配一个唯一 ID:

POST movies/_doc
{ "title": "Spirited Away" }

自动生成 ID 有一个明显的缺点:由于索引请求未指定文档 ID,您以后无法轻松更新该文档。此外,如果您运行此请求 10 次,OpenSearch 会将此文档索引为具有唯一 ID 的 10 个不同文档。要指定 ID 为 1,请使用以下请求(请注意使用 PUT 而不是 POST):

PUT movies/_doc/1
{ "title": "Spirited Away" }

由于您必须指定一个 ID,如果您运行此命令 10 次,您仍然只有一个文档被索引,并且 _version 字段会递增到 10。

索引默认包含一个主分片和一个副本。如果您想指定非默认设置,请在添加文档之前创建索引:

PUT more-movies
{ "settings": { "number_of_shards": 6, "number_of_replicas": 2 } }

索引命名限制

OpenSearch 索引有以下命名限制:

  • 所有字母必须是小写。
  • 索引名称不能以下划线 (_) 或连字符 (-) 开头。
  • 索引名称不能包含空格、逗号或以下字符:

    :"*+/\|?#><

读取数据

索引文档后,您可以通过向用于索引的相同端点发送 GET 请求来检索它:

GET movies/_doc/1

{
  "_index" : "movies",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "Spirited Away"
  }
}

您可以在 _source 对象中看到该文档。如果未找到文档,则 found 键为 false,并且 _source 对象不属于响应的一部分。

要使用单个命令检索多个文档,请使用 _mget 操作。检索多个文档的格式与 _bulk 操作类似,您必须在请求正文中指定索引和 ID:

GET _mget
{
  "docs": [
    {
      "_index": "<index>",
      "_id": "<id>"
    },
    {
      "_index": "<index>",
      "_id": "<id>"
    }
  ]
}

仅返回文档中的特定字段:

GET _mget
{
  "docs": [
    {
      "_index": "<index>",
      "_id": "<id>",
      "_source": "field1"
    },
    {
      "_index": "<index>",
      "_id": "<id>",
      "_source": "field2"
    }
  ]
}

检查文档是否存在:

HEAD movies/_doc/<doc-id>

如果文档存在,您将收到 200 OK 响应;如果不存在,您将收到 404 - Not Found 错误。

更新数据

要更新现有字段或添加新字段,请向 _update 操作发送 POST 请求,并将您的更改放在 doc 对象中:

POST movies/_update/1
{
  "doc": {
    "title": "Castle in the Sky",
    "genre": ["Animation", "Fantasy"]
  }
}

请注意更新后的 title 字段和新的 genre 字段:

GET movies/_doc/1

{
  "_index" : "movies",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "Castle in the Sky",
    "genre" : [
      "Animation",
      "Fantasy"
    ]
  }
}

该文档的 _version 字段也已递增。使用此字段来跟踪文档更新的次数。

POST 请求对文档进行部分更新。要完全替换文档,请使用 PUT 请求:

PUT movies/_doc/1
{
  "title": "Spirited Away"
}

ID 为 1 的文档将只包含 title 字段,因为整个文档将被此 PUT 请求中索引的文档替换。

使用 upsert 对象根据文档是否存在来有条件地更新文档。在这里,如果文档存在,其 title 字段将更改为 Castle in the Sky。如果不存在,OpenSearch 会索引 upsert 对象中的文档。

POST movies/_update/2
{
  "doc": {
    "title": "Castle in the Sky"
  },
  "upsert": {
    "title": "Only Yesterday",
    "genre": ["Animation", "Fantasy"],
    "date": 1993
  }
}

示例响应

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

文档的每个更新操作都具有 _seq_no_primary_term 值的唯一组合。

OpenSearch 首先将您的更新写入主分片,然后将此更改发送到所有副本分片。如果您的基于 OpenSearch 的应用程序的多个用户对同一索引中的现有文档进行更新,可能会出现一个不常见的问题。在这种情况下,另一个用户可能会在副本收到主分片的更新之前读取并更新文档。您的更新操作最终会更新文档的旧版本。在最好的情况下,您和其他用户进行相同的更改,并且文档保持准确。在最坏的情况下,文档现在包含过时的信息。

为了防止这种情况,请在请求头中使用 _seq_no_primary_term 值:

POST movies/_update/2?if_seq_no=3&if_primary_term=1
{
  "doc": {
    "title": "Castle in the Sky",
    "genre": ["Animation", "Fantasy"]
  }
}

如果文档在我们检索后被更新,_seq_no_primary_term 值将不同,并且我们的更新操作将以 409 - Conflict 错误失败。

使用 _bulk API 时,请在操作元数据中指定 _seq_no_primary_term 值。

删除数据

要从索引中删除文档,请使用 DELETE 请求:

DELETE movies/_doc/1

DELETE 操作会增加 _version 字段。如果您将文档添加回相同的 ID,_version 字段会再次递增。发生此行为是因为 OpenSearch 删除了文档的 _source,但保留了其元数据。

后续步骤

  • 索引管理 (IM) 插件允许您自动化重复的索引管理活动并降低存储成本。有关更多信息,请参阅索引状态管理

  • 有关如何重新索引数据的说明,请参阅重新索引数据

剩余 350 字符

有问题?

想贡献力量?