增删改查
> 文档中心 > 文档中心 > INFINI Easysearch > 功能手册 > 文档操作 > 增删改查

增删改查 #

您可以使用 REST API 对数据进行索引。存在两个 API:索引 API 和 _bulk API。

对于新数据增量到达的情况(例如,来自小型企业的客户订单),您可以使用索引 API 在文档到达时单独添加文档。对于数据流不太频繁的情况(例如,每周更新一次营销网站),您可能更希望生成一个文件并将其发送到 _bulk API。对于大量文档,将请求汇总在一起并使用 _bulk API 可提供优异的性能。然而,如果您的文档非常庞大,您可能需要单独对它们进行索引。

索引介绍 #

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

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

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

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

_bulk API 的请求看起来有点不同,因为您在批量数据中指定了索引和 ID:

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

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

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

文档是可选的,因为 删除 操作不需要文档。其他操作( 索引创建更新 )都需要文档。如果您特别希望在文档已存在的情况下操作失败,请使用 创建 操作而不是 索引 操作。

要使用 curl 命令对批量数据采用 _bulk API 进行索引,请导航到 data.json 文件的所在文件夹,然后运行以下命令:

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

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

Easysearch 的特点是当您将文档添加到不存在的索引时自动创建索引。如果不在请求中指定 ID,它还具有自动生成 ID 的功能。这个简单的示例会自动创建 movies 索引,为文档编制索引,并为其分配一个唯一的 ID:

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

自动生成 ID 有一个明显的缺点:因为索引请求没有指定文档 ID,所以以后无法轻松更新文档。此外,如果您运行此请求 10 次,Easysearch 会将此文档索引为具有唯一 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 } }

命名限制 #

Easysearch 索引具有以下命名限制:

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

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

检索数据 #

索引文档后,可以通过向用于索引的同一端点发送 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 。如果没有,Easysearch 将在 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 值的唯一组合。

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

要防止这种情况,请在请求头中使用 _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 字段将再次递增。出现这种行为是因为 Easysearch 删除了文档 _source ,但保留了其元数据。