参考答案:
在 Elasticsearch 中,更新和删除文档的过程与插入文档有一些不同。虽然它们都涉及到文档在 Elasticsearch 中的存储和管理,但具体的实现方式和细节有所区别。以下是 Elasticsearch 更新和删除文档的详细过程。
Elasticsearch 在进行文档更新时,并不会直接修改已存储的文档,而是通过以下步骤进行“更新”操作:
更新文档的实际过程是通过 删除旧文档 和 插入新文档 实现的。这个操作的核心思想是 不可变性,即文档一旦被写入,就不会被修改,修改实际上是创建一个新的文档,并删除旧的文档。
具体更新流程如下:
更新文档通常使用 update
API 来进行操作。它通常包含两部分:
doc
:包含需要更新的字段和新的值(仅更新部分字段,不更新整个文档)。upsert
:如果文档不存在,指定的文档将会被插入。例如,更新某个文档的某个字段:
1POST /index_name/_update/document_id 2{ 3 "doc": { 4 "field1": "new_value" 5 } 6}
如果文档不存在,则可以使用 upsert
来插入新文档:
1POST /index_name/_update/document_id 2{ 3 "doc": { 4 "field1": "new_value" 5 }, 6 "upsert": { 7 "field1": "new_value", 8 "field2": "default_value" 9 } 10}
当更新请求到达 Elasticsearch 集群时,处理过程如下:
路由到正确的分片:更新请求通过路由机制被路由到包含目标文档的分片。如果没有指定路由,则使用默认的 _id
进行路由。
删除旧文档:在分片上,Elasticsearch 会首先删除具有相同 _id
的文档。实际上,文档并不会立即从磁盘删除,而是被标记为删除。Lucene 会将该文档标记为“删除标记”,即 soft delete
。这意味着它在物理层面上并没有立刻从磁盘中移除,但它在后续的查询和索引更新中将被忽略。
插入新文档:随后,Elasticsearch 会将新的文档插入到索引中。这是一个插入新文档的过程,实际上是将新文档写入分片中的倒排索引,并根据新的文档重新计算倒排索引。
更新文档版本:在 Elasticsearch 中,每个文档都有一个版本号。当更新文档时,版本号会自增,表示该文档是一个新的版本。Elasticsearch 使用版本控制机制来保证文档更新时的并发一致性。
删除文档的过程与更新文档的部分流程相似。删除文档的核心操作是 标记删除,并在后台定期清理。
删除文档通常使用 delete
API 来执行,格式如下:
1DELETE /index_name/_doc/document_id
这个请求会从 Elasticsearch 中删除指定的文档。
当删除请求到达 Elasticsearch 集群时,处理过程如下:
路由到正确的分片:和更新操作一样,删除请求也通过路由机制路由到正确的分片。
标记文档为删除:Elasticsearch 会将目标文档标记为删除。实际上,Lucene 会对文档进行“软删除”(soft delete),即不会立即从磁盘上物理删除该文档,而是将其标记为删除。这个操作相对快速,Elasticsearch 会更新文档的元数据,标记它为已删除。
删除标记和删除合并:Elasticsearch 会将删除标记保留在内存中,并在适当的时候(如段合并操作)物理删除这些文档。在 Elasticsearch 的背景中,这一过程称为 segment merge,即将多个小的索引段合并为一个更大的索引段。在这个过程中,所有标记为删除的文档会被移除,释放磁盘空间。
在进行更新或删除操作时,Elasticsearch 会使用版本控制来防止并发修改问题。每次更新都会增加文档的版本号。默认情况下,Elasticsearch 会在更新时校验版本,确保没有并发更新操作。版本号的存在确保了更新操作的顺序一致性,避免丢失数据或覆盖更新。
虽然更新和删除文档的过程看似复杂,但 Elasticsearch 通过以下方式优化了这些操作:
最近更新时间:2024-12-12