----创建新文档----

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 创建、更新、删除文档、处理冲突的更多相关文章

  1. 2.MongoDB系列之创建更新删除文档

    1. 插入文档 // 单条插入 db.getCollection('blog').insertOne({'type': 'mongodb'}) // 批量 插入 db.getCollection('b ...

  2. 《mongoDB》基本操作-创建/更新/删除文档

    一:基本操作 - db; 当前选择的集合(等于数据库名) > db demo -  use db_name; 选择你要操作的集合 > use demo switched to db dem ...

  3. MongoDB(二)创建更新删除文档

    插入并保存文档操作 用insert向目标集合插入文档,如果没有_id键则会自动添加.最后自动保存. >db.foo.insert({"bar":"baz" ...

  4. MongoDB创建\更新\删除文档操作

     一.插入\创建文档 --当插入一个不存在的文档时,会自己主动创建一个文档 [root@racdb ~]# mongo MongoDB shell version: 2.4.14 connecti ...

  5. sharepoint中的Power Shell命令创建、删除文档库列表

    ListTemplateType 枚举: 自定义列表-GenericList.文档库-DocumentLibrary.图片库-PictureLibrary.公告-Announcements.联系人-C ...

  6. Elasticsearch 删除文档

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

  7. Elasticsearch 使用集群 - 创建和查询文档

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

  8. elasticsearch 第五篇(文档操作接口)

    INDEX API 示例: 1 2 3 4 5 PUT /test/user/1 { "name": "silence", "age": 2 ...

  9. 详细描述一下 Elasticsearch 更新和删除文档的过程?

    1.删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不 能被删除或者改动以展示其变更: 2.磁盘上的每个段都有一个相应的.del 文件.当删除请求发送后,文档并没有真 ...

随机推荐

  1. bzoj千题计划276:bzoj4515: [Sdoi2016]游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=4515 把lca带进式子,得到新的式子 然后就是 维护树上一次函数取min 一个调了一下午的错误: 当 ...

  2. 解决java.lang.NoSuchMethodError:org.joda.time.DateTime.withTimeAtStartOfDay() Lorg/joda/time/DateTime

    问题:项目放在weblogic运行,报错 java.lang.NoSuchMethodError: org.joda.time.DateTime.withTimeAtStartOfDay()Lorg/ ...

  3. LeetCode & Q414-Third Maximum Number-Easy

    Array Math Description: Given a non-empty array of integers, return the third maximum number in this ...

  4. python 人工智能资源推荐

    原创 2017-06-05 玄魂工作室 玄魂工作室 我翻了翻我自己曾经看过的书,还是放弃了推荐.原因很简单,我对这个领域并不是很熟悉,我来推荐资源有点误人子弟.so,简单推点其他人建议给我的内容,希望 ...

  5. C# 一个初学者对 依赖注入 IOC 的理解( 含 Unity 的使用)

    通过 人打电话 来谈谈自己对IOC的理解 版本1.0 public class Person { public AndroidPhone Phone { get; set; } public void ...

  6. mysql(1)—— 详解一条sql语句的执行过程

    SQL是一套标准,全称结构化查询语言,是用来完成和数据库之间的通信的编程语言,SQL语言是脚本语言,直接运行在数据库上.同时,SQL语句与数据在数据库上的存储方式无关,只是不同的数据库对于同一条SQL ...

  7. 【iOS】UIViewController基类的实现

    继承是面向对象编程语言的三大特性之一,写好基类会给App的开发带来极大的方便.在iOS开发中,一般一个页面就对应一个ViewController,ViewController在开发中用的也很多,写一个 ...

  8. [洛谷P1197/BZOJ1015][JSOI2008]星球大战Starwar - 并查集,离线,联通块

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...

  9. Iframe父页面与子页面之间的相互调用

    iframe元素就是文档中的文档. window对象: 浏览器会在其打开一个HTML文档时创建一个对应的window对象.但是,如果一个文档定义了一个或者多个框架(即:包含一个或者多个frame或者i ...

  10. 【Swift】swift中使用kvc赋值的时候,注意事项

    swift中使用kvc赋值的时候.假如给基础数据类型赋值,必须先给基础数据类型的变量一个初始值. 否则将会报错. var setValue(dict["id"], forKey: ...