Elasticsearch 创建、更新、删除文档、处理冲突
----创建新文档----
1._index,_type和_id的组合可以唯一标识一个文档,所以确保一个新文档的最简单的办法就是,使用索引请求的POST形式让elsticsearch自动生成唯一_id:
POST /website/blog
{ ... }
2.如果需要指定文档的_id,那就需要告诉elasticsearch在_index,_type和_id的组合不存在的时候进行新建操作,有两种方法实现
- 使用op_type
PUT /website/blog/123?op_type=create
{ ... }
- 在URL末端使用/_create
PUT /website/blog/123/_create
{ ... }
注意: 请求执行成功会返回元数据(执行结果)和一个201 Created 的HTTP响应码。
如果相同_index,_type和_id的组合的文档已经存在,elasticsearch将会返回409 Conflict 响应码以及如下错误信息。
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[blog][124]: version conflict, document already exists (current version [1])",
"index_uuid": "oCXgGtl9SfmXXD-edmYdfA",
"shard": "3",
"index": "website"
}
],
"type": "version_conflict_engine_exception",
"reason": "[blog][124]: version conflict, document already exists (current version [1])",
"index_uuid": "oCXgGtl9SfmXXD-edmYdfA",
"shard": "3",
"index": "website"
},
"status": 409
}
----删除文档----
删除文档,使用DELETE 方法:
DELETE /website/blog/123
一如果找到该文档,elasticsearch将返回一个200 ok 的HTTP响应码,和一个类似以下结构的响应体,字段_version 值会增加。
{
"found": true,
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 6,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
}
}
标如果文档没有找到,我们将会得到一个404 not Found 的响应码和一个类似以下结构的响应体,即便文档不存在,_version值也会增加,这是 Elasticsearch 内部记录本的一部分,用来确保这些改变在跨多节点时以正确的顺序执行。
{
"found": false,
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 3,
"result": "not_found",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
}
}
注意:
正如已经在更新整个文档中提到的,删除文档不会立即将文档从磁盘中删除,只是将文档标记为已删除状态。随着你不断的索引更多的数据,Elasticsearch 将会在后台清理标记为已删除的文档。
----处理冲突----
多个用户对一份数据进行修改操作时,变更越频繁,读数据和更新数据的间隙越长,也就越可能丢失变更。
在数据库领域中,有两种方法通常被用来确保并发更新时变更不会丢失:
1.悲观并发控制(悲观锁)
这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。
2.乐观并发控制(乐观锁)
Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。
Elasticsearch 是分布式的,当文档创建,更新或者删除时,新版本的文档必须复制到集群中的其他节点。
Elasticsearch 也是异步和并发的,这意味着这些复制请求被并行发送,并且到达目的地时顺序也许是乱的。Elasticsearch 需要一种方法确保文档的旧版本不会覆盖新的版本。
可以通过_version的递增来确保变更正确的执行顺序,简单的忽略掉旧版本的文档在新版本之后到达的操作。
# 创建一个测试的文档
PUT /website/blog/1/_create
{
"title": "My first blog entry",
"text": "Just trying this out..."
}
# 得到该文档的version版本号
GET /website/blog/1
# 尝试通过重建文档的索引来保存修改,我们指定 version 为我们的修改会被应用的版本,这个操作只有在version=1的时,更新才能成功
PUT /website/blog/1?version=1
{
"title": "My first blog entry",
"text": "Starting to get the hang of this..."
}
# 更新成功后,_vetsion递增
# 重新运行相同的索引请求,仍然指定 version=1 , Elasticsearch 返回 409 Conflict HTTP 响应码
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[blog][1]: version conflict, current version [2] is different than the one provided [1]",
"index_uuid": "oCXgGtl9SfmXXD-edmYdfA",
"shard": "3",
"index": "website"
}
],
"type": "version_conflict_engine_exception",
"reason": "[blog][1]: version conflict, current version [2] is different than the one provided [1]",
"index_uuid": "oCXgGtl9SfmXXD-edmYdfA",
"shard": "3",
"index": "website"
},
"status": 409
}
注:所有文档的更新或删除 API,都可以接受 version 参数,这允许你在代码中使用乐观的并发控制
3.通过外部系统使用版本控制
一个常见的设置是使用其它数据库作为主要的数据存储,使用 Elasticsearch 做数据检索, 这意味着主数据库的所有更改发生时都需要被复制到 Elasticsearch ,如果多个进程负责这一数据同步,你可能遇到类似于之前描述的并发问题。
如果你的主数据库已经有了版本号 — 或一个能作为版本号的字段值比如 timestamp — 那么你就可以在 Elasticsearch 中通过增加 version_type=external 到查询字符串的方式重用这些相同的版本号, 版本号必须是大于零的整数, 且小于 9.2E+18 — 一个 Java 中 long 类型的正值。
外部版本号的处理方式和我们之前讨论的内部版本号的处理方式有些不同, Elasticsearch 不是检查当前 _version 和请求中指定的版本号是否相同, 而是检查当前 _version 是否 小于 指定的版本号。 如果请求成功,外部的版本号作为文档的新 _version 进行存储。
外部版本号不仅在索引和删除请求是可以指定,而且在 创建 新文档时也可以指定。
要创建一个新的具有外部版本号 5 的博客文章,我们可以按以下方法进行:
PUT /website/blog/2?version=5&version_type=external
{
"title": "My first external blog entry",
"text": "Starting to get the hang of this..."
}
在响应中,我们能看到当前的 _version 版本号是 5 :
{
"_index": "website",
"_type": "blog",
"_id": "2",
"_version": 5,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"created": true
}
现在我们更新这个文档,指定一个新的 version 号是 10 :
PUT /website/blog/2?version=10&version_type=external
{
"title": "My first external blog entry",
"text": "Starting"
}
请求成功并将当前 _version 设为 10 :
{
"_index": "website",
"_type": "blog",
"_id": "2",
"_version": 10,
"result": "updated",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"created": false
}
注:如果你要重新运行此请求时,它将会失败,并返回像我们之前看到的同样的冲突错误, 因为指定的外部版本号不大于 Elasticsearch 的当前版本号。
Elasticsearch 创建、更新、删除文档、处理冲突的更多相关文章
- 2.MongoDB系列之创建更新删除文档
1. 插入文档 // 单条插入 db.getCollection('blog').insertOne({'type': 'mongodb'}) // 批量 插入 db.getCollection('b ...
- 《mongoDB》基本操作-创建/更新/删除文档
一:基本操作 - db; 当前选择的集合(等于数据库名) > db demo - use db_name; 选择你要操作的集合 > use demo switched to db dem ...
- MongoDB(二)创建更新删除文档
插入并保存文档操作 用insert向目标集合插入文档,如果没有_id键则会自动添加.最后自动保存. >db.foo.insert({"bar":"baz" ...
- MongoDB创建\更新\删除文档操作
一.插入\创建文档 --当插入一个不存在的文档时,会自己主动创建一个文档 [root@racdb ~]# mongo MongoDB shell version: 2.4.14 connecti ...
- sharepoint中的Power Shell命令创建、删除文档库列表
ListTemplateType 枚举: 自定义列表-GenericList.文档库-DocumentLibrary.图片库-PictureLibrary.公告-Announcements.联系人-C ...
- Elasticsearch 删除文档
章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...
- Elasticsearch 使用集群 - 创建和查询文档
章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...
- elasticsearch 第五篇(文档操作接口)
INDEX API 示例: 1 2 3 4 5 PUT /test/user/1 { "name": "silence", "age": 2 ...
- 详细描述一下 Elasticsearch 更新和删除文档的过程?
1.删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不 能被删除或者改动以展示其变更: 2.磁盘上的每个段都有一个相应的.del 文件.当删除请求发送后,文档并没有真 ...
随机推荐
- Vim 中文社区:期待你的加入
我们的愿景 Vim 中文社区一直比较零散,缺少凝聚力,现有的一些群经常也是水的可以的,讨论各种无关紧要的内容,于是导致很大一部分人,将这些群丢入了群助手,渐渐地他们也淡出了 vim 中文社区. 而我理 ...
- JAVA线程池原理详解(1)
线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线 ...
- Linux入门:vi 和 vim
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器. 本文介绍了vi (vim)的基本使用方法,但对于普通用户来说基本上够了! 转自:http://www.l ...
- 怎样使用下载的bootstrap模板?
核心文件bootstarp.css和bootstarp.js导入到页面,然后看着官网的代码复制进去用就可以了.网上是有不少教程的.实际上就是加class 属性 ,如:http://www.runoob ...
- Spring Security入门(3-6)Spring Security 的鉴权 - 自定义权限前缀
- Spring Security 入门(1-8)缓存EhCache
- python学习之路01
python自己也自学过一段时间了,看过视频,也买过几本基础的书来看,目前为止对于一些简单的代码还是可以看懂,但是自己总是觉得缺少些什么,可能是缺少系统化的学习,也可能是缺少实际项目经验,对于这些缺少 ...
- 使用Java High Level REST Client操作elasticsearch
Java高级别REST客户端(The Java High Level REST Client)以后简称高级客户端,内部仍然是基于低级客户端.它提供了更多的API,接受请求对象作为参数并返回响应对象,由 ...
- Python之线程
操作系统线程理论 线程概念的引入背景 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别 ...
- nohup 与 & 的区别
nohup -- invoke a utility immune to hangups : 运行命令忽略挂起信号 & 是指后台运行: nohup 的功能和& 之间的功能并不相同.其中, ...