管理索引

你可以使用 UDB-SX REST API 来索引数据。存在两种 API:索引 API 和 _bulk API。

对于新数据逐步到达的场景(例如,小企业的客户订单),可以使用索引 API 在数据到达时逐个添加文档。对于数据流不太频繁的场景(例如,营销网站的每周更新),推荐生成一个文件并将其发送到 _bulk API。对于大量文档,将请求集中在一起并使用 _bulk API 可以提供更好的性能。然而,如果文档非常大,可能需要单独索引它们。

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

索引简介

在你能够搜索数据之前,你必须对其进行 索引。索引是搜索引擎组织数据以实现快速检索的方法。由此产生的结构被称为索引。

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

对索引 API 的请求如下所示:

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

_bulk API 的请求两行一组:第一行 = 操作头,第二行 = 文档内容,如下所示:

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 操作。使用的 create 操作时,只有文档不存在才创建,若文档已存在则报错;使用 index 操作时,如果文档已存在,则替换该文档。

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

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

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

当用户向尚不存在的索引添加文档时,UDB-SX 会自动创建该索引。如果你在请求中没有指定 ID,它还会自动生成一个 ID。这个简单的示例自动创建了电影索引,索引了文档,并为其分配了一个唯一 ID:

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

自动生成 ID 有一个明显的缺点:由于索引请求没有指定文档 ID,用户以后无法轻松更新该文档。此外,如果用户运行此请求 10 次,UDB-SX 会将此文档作为 10 个具有唯一 ID 的不同文档进行索引。要指定 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 } }

索引的命名限制

UDB-SX 索引有以下命名限制:

  • 所有字母必须小写。

  • 索引名称不能以下划线(_)或连字符(-)开头。

  • 索引名称不能包含空格、逗号或以下字符:

    :, ", *, +, /, \, |, ?, #, >, 或 <

读取数据

索引文档后,用户可以通过向用于索引的同一端点发送 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",
  "_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。如果不存在,UDB-SX 将索引 upsert 对象中的文档。

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

示例响应

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

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

UDB-SX 首先将你的更新写入主分片,然后将此更改发送到所有副本分片。一个罕见的问题可能发生在多个用户你的基于 UDB-SX 的应用程序在同一索引中更新现有文档的情况下。在这种情况下,另一个用户可以在副本收到来自主分片的更新之前从副本读取和更新文档。然后,你的更新操作最终会更新一个旧版本的文档。在最好的情况下,你和另一个用户进行相同的更改,文档保持准确。在最坏的情况下,文档现在包含过时的信息。

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

POST movies/_update/1?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 字段会再次递增。这种行为发生是因为 UDB-SX 删除了文档的 _source,但保留了其元数据。