5、 UPDATE API

更新操作可以使用脚本来更新。更新的时候会先从索引中获取文档数据(在每个分片中的集合),然后运行脚本(使用可选的脚本语言和参数),再果进行索引(还允许删除或忽略该操作)。它使用版本号保证在读取文档和重新索引期间,被更新的文档不会发生任何修改操作。

注意,update操作会重新索引文档,它可以减少网络往返次数和降低在获取文档和索引文档之间发生版本号冲突的可能。要支持这一特性,需要开启_source字段(因为要读取旧数据,和替换操作不一样,替换操作不需要读旧数据).

例如,让我们索引一个简单的文档:

  1. PUT test/type1/1
  2. {
  3. "counter" : 1,
  4. "tags" : ["red"]
  5. }

5.1 使用脚本更新(Scripted updates)

增加counter字段的值:

  1. POST test/type1/1/_update
  2. {
  3. "script" : {
  4. "inline": "ctx._source.counter += params.count",
  5. "lang": "painless",
  6. "params" : {
  7. "count" : 4
  8. }
  9. }
  10. }

tags字段增加一个元素:

  1. POST test/type1/1/_update
  2. {
  3. "script" : {
  4. "inline": "ctx._source.tags.add(params.tag)",
  5. "lang": "painless",
  6. "params" : {
  7. "tag" : "blue"
  8. }
  9. }
  10. }

除了_source,下面的变量是可用下面的字段都可以在ctx使用:_index, _type, _id, _version, _routing, _parent, and _now(当前时间)

新增文档字段:

  1. POST test/type1/1/_update
  2. {
  3. "script" : "ctx._source.new_field = \"value_of_new_field\""
  4. }

删除文档字段:

  1. POST test/type1/1/_update
  2. {
  3. "script" : "ctx._
  4. source.remove(\"new_field\")"
  5. }

甚至可以改变当前操作,并支持逻辑判断,如果tags包含green就执行删除操作,否则什么都不做:

  1. POST test/type1/1/_update
  2. {
  3. "script" : {
  4. "inline": "if (ctx._source.tags.contains(params.tag)) { ctx.op = \"delete\" } else { ctx.op = \"none\" }",
  5. "lang": "painless",
  6. "params" : {
  7. "tag" : "green"
  8. }
  9. }
  10. }

5.1 脚本更新(Scripted updates)

现在执行一个增加计数器的脚本:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : {
  4. "source": "ctx._source.counter += params.count",
  5. "lang": "painless",
  6. "params" : {
  7. "count" : 4
  8. }
  9. }
  10. }

下例表示在标签列表中添加一个标签(如果标签存在,它仍会被添加,因为这是一个列表):

  1. POST test/_doc/1/_update
  2. {
  3. "script" : {
  4. "source": "ctx._source.tags.add(params.tag)",
  5. "lang": "painless",
  6. "params" : {
  7. "tag" : "blue"
  8. }
  9. }
  10. }

可以从标签列表中删除标签。请注意,painless 的 remove 函数是需要你删除的 tag 的 index,因此需要使用更多的逻辑来获取它以避免运行时出错。请注意,如果要删除的 tag 在 tags 里面出现多次,但是只会删除一次。:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : {
  4. "source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }",
  5. "lang": "painless",
  6. "params" : {
  7. "tag" : "blue"
  8. }
  9. }
  10. }

除了_source之外,ctx 的这些值也可以用:_index_type_id_version_routing_now(当前时间戳)。

我们也可以这样添加一个字段:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : "ctx._source.new_field = 'value_of_new_field'"
  4. }

或是这样删除一个字段:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : "ctx._source.remove('new_field')"
  4. }

我们甚至可以指定 ctx 的操作,如下判断 tags 是否包含 green,如果包含则删除文档,否则不进行任何操作:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : {
  4. "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }",
  5. "lang": "painless",
  6. "params" : {
  7. "tag" : "green"
  8. }
  9. }
  10. }

5.2 局部更新文档(Updates with a partial document)

update API 也支持将部分文档合并到现有文档中(简单的递归合并,对象的属性合并、替换属性值和数组)。要完全替换现有的文档,应使用 index API。以下的部分更新将向现有文档中添加新的字段:

  1. POST test/_doc/1/_update
  2. {
  3. "doc" : {
  4. "name" : "new_name"
  5. }
  6. }

如果docscript一起指定,doc将会被忽略。最好的更新方式是将部分文档的字段对放在脚本本身中。

5.3 检查空操作(Detecting noop updates)

如果指定了doc,则其值将与现有的_source合并。默认情况下,不进行任何内容更改的更新操作会检测到它们不更改任何内容并返回"result": "noop"如下:

  1. POST test/_doc/1/_update
  2. {
  3. "doc" : {
  4. "name" : "new_name"
  5. }
  6. }

如果name的值在更新前本来就是new_name,那么这个操作将会被忽略。返回结果的result字段将会是noop

  1. {
  2. "_shards": {
  3. "total": 0,
  4. "successful": 0,
  5. "failed": 0
  6. },
  7. "_index": "test",
  8. "_type": "_doc",
  9. "_id": "1",
  10. "_version": 7,
  11. "result": "noop"
  12. }

你可以通过设置 detect_noopfalse来禁止 noop,如:

  1. POST test/_doc/1/_update
  2. {
  3. "doc" : {
  4. "name" : "new_name"
  5. },
  6. "detect_noop": false
  7. }

5.4 Upserts

如果文档不存在,就创建一个 与upsert字段内容一致的文档,如果文档存在就执行script中的更新操作:

  1. POST test/_doc/1/_update
  2. {
  3. "script" : {
  4. "source": "ctx._source.counter += params.count",
  5. "lang": "painless",
  6. "params" : {
  7. "count" : 4
  8. }
  9. },
  10. "upsert" : {
  11. "counter" : 1
  12. }
  13. }

5.4.1 scripted_upsert

如果你想不管文档存不存在都要执行script(即,用script来初始化文档而不是upsert字段),那么需要设置scripted_upserttrue

  1. POST sessions/session/dh3sgudg8gsrgl/_update
  2. {
  3. "scripted_upsert":true,
  4. "script" : {
  5. "id": "my_web_session_summariser",
  6. "params" : {
  7. "pageViewEvent" : {
  8. "url":"foo.com/bar",
  9. "response":404,
  10. "time":"2014-01-01 12:32"
  11. }
  12. }
  13. },
  14. "upsert" : {}
  15. }

5.4.2 doc_as_upsert

doc_as_upsert设置为true,将会把 doc 中的值按照upsert执行:

  1. POST test/_doc/1/_update
  2. {
  3. "doc" : {
  4. "name" : "new_name"
  5. },
  6. "doc_as_upsert" : true
  7. }

5.5 参数(Parameters)

update操作支持如下查询参数:

  • retry_on_conflict

    • 在更新的get和indexing阶段之间,另一个进程可能已经更新了同一文档。默认情况下,更新会因版本冲突而失败。retry_on_conflict参数指定更新失败时重试多少次
  • routing
    • routing参数用于将更新请求路由到正确的分片。如果索引的时候指定了该参数,更新的时候也要指定同样的值。在使用upsert字段时,如果文档不存在的时候,就会创建新文档,此时可以指定这个文档的路由值。不能更新一个已存在的文档的routing(就是说不能把文档从一个分片移动到另一个分片)。
  • timeout
    • 等待分片变成可用状态的最大时间
  • wait_for_active_shards
    • 在执行更新操作前,至少有多少个可用的分片才能执行更新操作。详细请查阅
  • refresh
    • 控制此请求所做的更改何时对搜索可见。请查阅refresh
  • _source
    • 控制是否以及如何响应更新后的文档,默认不是会返回已更新的_source字段。查阅soruce filtering
  • version
    • update API 使用 Elasticsearch 内部版本控制,以确保在更新期间文档不会被其他进程更新。你可以使用version参数指定仅在version和文档版本号一致时才更新文档。(在6.7.0中version以被弃用。请改用if_seq_no和if_primary_term,有关更多详细信息,请参阅乐观并发控制。)

update API不支持内部版本以外的版本控制

update API 不支持外部(externalexternal_gte 版本类型)或强制(force 版本类型)版本控制,这会导致 Elasticsearch 版本号与外部系统不同步。(比如外部版本号可以为0,但是内部版本号不可以为0)。你可以使用indexAPI 代替这个操作。

  • if_seq_noif_primary_term

    • 更新操作可以是有条件的,只有在为文档的最后一次修改分配了if_seq_no和if_primary_term参数指定的序列号和主要术语时才能执行。如果检测到不匹配,则操作将导致VersionConflictException和状态代码409.有关详细信息,请参阅乐观并发控制

elasticsearch6.7 05. Document APIs(6)UPDATE API的更多相关文章

  1. elasticsearch6.7 05. Document APIs(3)GET API

    2.GET API get API 可以通过文档id从索引中获取json格式的文档,以下示例从twitter索引中获取type为_doc,id值为0为的JSON文档: GET twitter/_doc ...

  2. elasticsearch6.7 05. Document APIs(2)Index API

    Single document APIs Index API Get API Delete API Update API Multi-document APIs Multi Get API Bulk ...

  3. elasticsearch6.7 05. Document APIs(9)Bulk API

    8.Bulk API 可以把多个index或delete操作放在单个bulk API中执行.这样可以极大地提高索引速度. /_bulkAPI使用如下的JSON结构: action_and_meta_d ...

  4. elasticsearch6.7 05. Document APIs(7)Update By Query API

    6.Update By Query API _update_by_query 接口可以在不改变 source 的情况下对 index 中的每个文档进行更新.这对于获取新属性或其他联机映射更改很有用.以 ...

  5. elasticsearch6.7 05. Document APIs(4)Delete API

    3.Delete API delete API 可以让你删除一个特定id的文档,下面例子删除twitter索引中_doc类型.id为1的文档: DELETE /twitter/_doc/1 返回结果: ...

  6. elasticsearch6.7 05. Document APIs(10)Reindex API

    9.REINDEX API Reindex要求为源索引中的所有文档启用_source. reindex 不会配置目标索引,不会复制源索引的设置.你需要在reindex之前先指定mapping,分片数量 ...

  7. elasticsearch6.7 05. Document APIs(5)Delete By Query API

    4.Delete By Query API _delete_by_query API可以删除某个匹配条件的文档: POST twitter/_delete_by_query { "query ...

  8. elasticsearch6.7 05. Document APIs(8)Multi Get API

    7.Multi Get API(Multi Get API) multi GET API 允许你一次性获取多个文档,你需要指定docs数组,其中包含了所有你需要查询的文档,每个查询结构至少包含索引,类 ...

  9. elasticsearch6.7 05. Document APIs(1)data replication model

    data replication model 本节首先简要介绍Elasticsearch的data replication model,然后详细描述以下CRUD api: 1.读写文档(Reading ...

随机推荐

  1. 第一个Python小爬虫

    这个爬虫是参考http://python.jobbole.com/81353/这篇文章写的 这篇文章可能年代过于久远,所以有些代码会报错,然后我自己稍微修改了一下,增加了一个getContentAll ...

  2. 向Word添加一段文本

    文档层次结构 [段落之后] 是一段连续文本,它定义具有一组常见属性的文本区域.一段连续文本由 r 元素表示,这样创建器便可组合换行.样式或格式设置属性,从而将相同信息应用于一段连续文本的所有部分. 正 ...

  3. Codeforces Round #540 (Div. 3)--1118C - Palindromic Matrix

    https://codeforces.com/contest/1118/problem/C 在查找元素的时候,必须按4,2,1的顺序进行.因为,如果先找1,可能就把原来的4拆散了,然后再找4,就找不到 ...

  4. 2017-2018-1 20155326信息安全系统设计基础》嵌入式C语言课上考试补交

    2017-2018-1 20155326信息安全系统设计基础>嵌入式C语言课上考试补交 PPT上的例子 已知位运算规则为: &0 --> 清零 &1 --> 不变 | ...

  5. JDBC创建链接的几种方式

    首先,使用java程序访问数据库的前提 数据库的主机地址(ip地址) 端口 数据库用户名 数据库用户密码 连接的数据库 代码: private static String url = "jd ...

  6. CASUAL_NCT

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Da ...

  7. WPF PrismDialog PopupWindowAction使用MetroWindow

    本示例必须在prism5.0版本以上 PopupWindowAction如何使用MetroWindow?   public class Window1ViewModel:BindableBase,II ...

  8. ajax跨域问题小结

    跨域:跨域名的访问,是浏览器对ajax的一种限制,这样可以有效的房子跨站攻击 跨域的范畴: 域名不同  或 端口不同 或 二级域名不同 解决方案: 第一种:由于前端基础薄弱,且该方式老掉牙,不讲解: ...

  9. C++数组,sort

    cmake_minimum_required(VERSION 3.5) project(Test) add_executable( te test.cpp ) test.cpp #include &l ...

  10. SQL注入之重新认识

    i春秋作家:anyedt 原文来自:https://bbs.ichunqiu.com/thread-41701-1-1.html 引言 作为长期占据 OWASP Top 10 首位的注入,认识它掌握它 ...