本文主要是介绍07.update和upsert操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. Update API 简介
- 2. 使用脚本更新
- 3. 非script的部分文档更新
- 4. 检测空操作更新 noop updates
- 5. Upserts
- 1. scripted_upsert
- 2. doc_as_upsert
- 6. 参数
1. Update API 简介
update API 允许基于script脚本来更新doc。对应的操作从index当中获取doc,然后run script, 然后再将修改后的doc indexing到原来的index。在这个过程中使用了version控制,以便于确保在获取和重新索引没有更新发生。
注意,此操作仍然意味着对文件做重新的全索引。它只是删除了一些网络往返,减少了在索引和获取时候版本冲突的几率。 _source需要启用此功能工作。
例如:一个简单的索引文件:
PUT test/_doc/1
{"counter" : 1,"tags" : ["red"]
}
2. 使用脚本更新
现在,我们可以执行一个脚本,用做计数器:
POST test/_update/1
{"script" : {"source": "ctx._source.counter += params.count","lang": "painless","params" : {"count" : 4}}
}
我们可以添加标签来进行标记(注意,如果标签存在,仍然会添加,因为是一个列表)
POST test/_update/1
{"script" : {"source": "ctx._source.tags.add(params.tag)","lang": "painless","params" : {"tag" : "blue"}}
}
我们可以从标签列表中删除标签。请注意,删除标签的painless的remove函数将要删除的元素的数组索引作为其参数,因此需要更多的逻辑来定位它,同时避免运行时错误。请注意,如果该标签在列表中出现多次,则只会删除一次该标签
POST test/_update/1
{"script" : {"source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }","lang": "painless","params" : {"tag" : "blue"}}
}
除了_source,下列变量通过 ctx map 都是可用的:_index,_type,_id,_version,_routing,_parent,和_now(当前的时间戳)。
我们也可以将新字段添加到文档:
POST test/_update/1
{"script" : "ctx._source.new_field = 'value_of_new_field'"
}
或者从文件中删除字段:
POST test/_update/1
{"script" : "ctx._source.remove('new_field')"
}
而且,我们甚至可以改变已执行的操作。这个例子就是如果 tags包含 green删除文档,否则就什么也不做(noop):
POST test/_update/1
{"script" : {"source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }","lang": "painless","params" : {"tag" : "green"}}
}
3. 非script的部分文档更新
更新 API 还支持部分文档的更新,将合并到现有的文件(简单的递归合并,内合并,更换核心“键/值”对和数组)。例如:
POST test/_update/1
{"doc" : {"name" : "new_name"}
}
如果同时 doc 和 script 被指定,那么 doc将被忽略。推荐的做法是使用script来update部分文档。
4. 检测空操作更新 noop updates
默认情况下回进行无更新检测,当要merged的doc片段和原有的doc中的字段是一致的话,不会有更新操作产生,在response当中会有一个"result": "noop"
标识
比如下面的操作
POST test/_update/1
{"doc" : {"name" : "new_name"}
}
如果 name字段在这个秦秋之前就是 new_name,那么整个更新请求会被忽略。如果请求被忽略了,在 result响应中的返回 noop。
{"_shards": {"total": 0,"successful": 0,"failed": 0},"_index": "test","_type": "_doc","_id": "1","_version": 7,"result": "noop"
}
你可以通过设置 “detect_noop” 禁用此行为:
POST test/_update/1
{"doc" : {"name" : "new_name"},"detect_noop": false
}
5. Upserts
如果该文件存在,那么 script将执行。如果该文件不存在,则upsert内容将被插入作为一个新的文档。
POST test/_update/1
{"script" : {"source": "ctx._source.counter += params.count","lang": "painless","params" : {"count" : 4}},"upsert" : {"counter" : 1}
}
上面的请求如果_id为1的doc不存在的话,会插入一个文档,source中只有一个字段,是counter:1
1. scripted_upsert
如果你想你的脚本无论该文件存在与否都要运行-即脚本处理初始化文件而不是 upsert -然后设置 scripted_upsert为 true:
POST sessions/_update/dh3sgudg8gsrgl
{"scripted_upsert":true,"script" : {"id": "my_web_session_summariser","params" : {"pageViewEvent" : {"url":"foo.com/bar","response":404,"time":"2014-01-01 12:32"}}},"upsert" : {}
}
2. doc_as_upsert
doc 添加一个 upsert文档,设置 doc_as_upsert为 true ,将使用 doc 内容作为 upsert 值:
POST test/_update/1
{"doc" : {"name" : "new_name"},"doc_as_upsert" : true
}
6. 参数
更新操作支持以下查询字符串参数:
retry_on_conflict 在更新的 get 和 index 时,它可能是另一种方法可能已经更新了相同的文件。默认情况下,更新将失败,版本冲突异常。该 retry_on_conflict 参数控制抛出异常之前重试更新的次数。
routing 用于追踪更新请求正确的分片,如果文档更新不存在把其设置为更新插入请求。不能用于更新现有文档的路径。
timeout 超时等待一个分片变得可用。
wait_for_active_shards 在更新操作时,复制分片需要处在活跃状态的数目。
refresh 控制被该请求所做更改时进行的搜索。
_source 允许控制是否以及更新源如何在响应中返回。默认情况下不返回更新的源。见 source_filtering 详情。
version 更新 API 使用 Elasticsearch 的internal version。您可以使用 version 参数指定版本,如果文件匹配那么指定的文件需要更新。
if_seq_no and if_primary_term: 可以用来做并发控制,可以控制仅在文档的最后一次因为修改分配的_seq_no和_primary_term 参数和请求时传进来的if_seq_no和if_primary_term参数相等的情况下才能执行操作。如果检测到不匹配,则该操作将导致VersionConflictException和状态码409。
注意:
update api只支持internal version,External (version types external and external_gte) 是不支持的。
这篇关于07.update和upsert操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!