背景:
使用elasticsearch-rest-high-level-client 对ES进行更新操作,用seqNo来校验版本,现在报版本冲突错误如下:
Elasticsearch exception [type=version_conflict_engine_exception, reason=[type][_id]: version conflict, required seqNo [1222528], primary term [1]. current document has seqNo [1292133] and primary term [1]]
引用的maven文件
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.0.1</version>
</dependency>
查看官网文档:https://www.elastic.co/guide/en/elasticsearch/reference/2.2/docs-update.html#_parameters_3,
发现有一个配置项 retry_on_conflict,代表更新失败时重连次数,那就加上,版本冲突报错减少
解决:
RestClientBuilder builder = RestClient.builder(new HttpHost("127.0.0.1", 9200, "http"));
//ssl认证
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("账号一般是elastic", "密码"));
builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider));
builder.setRequestConfigCallback(requestConfigBuilder -> requestConfigBuilder
.setConnectTimeout(50000)
.setMaxRedirects(3)
.setSocketTimeout(150000));
RestHighLevelClient client = new RestHighLevelClient(builder);
JSONObject jObject = new JSONObject();
jObject.put("uu_id", 1);
jObject.put("username", "zhagnsan");
jObject.put("password", "password");
client.update(new UpdateRequest("index", "type", "更新ID").retryOnConflict(3)
.docAsUpsert(true).doc(jObject), RequestOptions.DEFAULT);
有兴趣了解更多的可以看下面官网的解释,逐步加深理解
更新API
更新API允许基于提供的脚本来更新文档。该操作从索引中获取文档(与分片并置),运行脚本(具有可选的脚本语言和参数),并向后索引结果(还允许删除或忽略该操作)。它使用版本控制来确保在“获取”和“重新索引”期间未发生任何更新。
注意,此操作仍然意味着对文档进行完全重新索引,它只是消除了一些网络往返,并减少了获取和索引之间版本冲突的机会。_source
需要启用此功能的字段。
例如,让我们为一个简单的文档建立索引:
curl - XPUT本地主机:9200 / test / type1 / 1 - d '{ “ counter” :1 ,“ tags” :[ “ red” ] } '
脚本更新
现在,我们可以执行一个脚本来增加计数器:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :{ “ inline” :“ ctx._source.counter + = count” ,“ params” :{ “ count” :4 } } } '
我们可以将标签添加到标签列表中(请注意,如果标签存在,它仍会添加标签,因为它是列表):
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :{ “ inline” :“ ctx._source.tags + = tag” ,“ params” :{ “ tag” :“蓝色“ } } } '
此外_source
,下列变量都可以通过ctx
地图:_index
,_type
,_id
,_version
,_routing
, _parent
,_timestamp
,_ttl
。
我们还可以在文档中添加一个新字段:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :“ ctx._source.name_of_new_field = \” value_of_new_field \“” } '
或从文档中删除一个字段:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :“ ctx._source.remove(\” name_of_field \“)” } '
而且,我们甚至可以更改执行的操作。如果tags
字段包含blue
,则此示例删除doc ,否则不执行任何操作(noop
):
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :{ “ inline” :“ ctx._source.tags.contains(tag)?ctx.op = \” delete \“ :ctx.op = \“ none \”“ ,” params“ :{ ” tag“ :” blue“ } } } '
使用部分文档进行更新
更新API还支持传递部分文档,该文档将合并到现有文档中(简单的递归合并,对象的内部合并,替换核心“键/值”和数组)。例如:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ doc” :{ “ name” :“ new_name” } } '
如果同时指定doc
和script
,则将doc
被忽略。最好是将部分文档的字段对放在脚本本身中。
检测noop更新
如果doc
指定,则其值将与现有合并_source
。默认情况下,仅当新_source
字段与旧字段不同时才对文档重新索引。设置detect_noop
为false
会导致Elasticsearch始终更新文档,即使文档没有更改。例如:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ doc” :{ “ name” :“ new_name” },“ detect_noop” :false } '
如果name
是new_name
在发送请求之前,则文档仍会重新编制索引。
增补
如果文档尚不存在,则upsert
元素的内容将作为新文档插入。如果文档确实存在,则将 script
改为执行:
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ script” :{ “ inline” :“ ctx._source.counter + = count” ,“ params” :{ “ count” :4 } },“ upsert” :{ “ counter” :1 } } '
scripted_upsert
如果您希望脚本运行而不管文档是否存在(即脚本处理初始化文档而不是 upsert
元素),请设置scripted_upsert
为true
:
curl - XPOST'localhost :9200 / sessions / session / dh3sgudg8gsrgl / _update' - d '{ “ scripted_upsert” :true ,“ script” :{ “ id” :“ my_web_session_summariser” ,“ params” :{ “ pageViewEvent” :{ “ url“ :” foo.com/bar“ ,” response“ :404 ,” time“ :” 2014-01-01 12:32“ } } },” upsert“ :{} } '
doc_as_upsert
设置为,而不是发送部分文档doc
和upsert
文档, 而是将的内容用作 值:doc_as_upsert
true
doc
upsert
curl - XPOST'localhost :9200 / test / type1 / 1 / _update' - d '{ “ doc” :{ “ name” :“ new_name” },“ doc_as_upsert” :true } '
参量
更新操作支持以下查询字符串参数:
| 在更新的获取和索引编制阶段之间,可能有另一个进程可能已经更新了同一文档。默认情况下,更新将因版本冲突异常而失败。该 |
| 路由用于将更新请求路由到正确的分片,并且如果不存在要更新的文档,则为upsert请求设置路由。不能用于更新现有文档的路由。 |
| 如果不存在要更新的文档,则使用父级将更新请求路由到正确的分片,并为更新请求设置父级。不能用于更新 |
| 等待分片可用的超时。 |
| 索引/删除操作的写入一致性。 |
| 操作发生后立即刷新相关的主和副本分片(而不是整个索引),以便更新后的文档立即出现在搜索结果中。 |
| 返回更新后的文档中的相关字段。指定 |
| 更新API在内部使用Elasticsearch的版本控制支持,以确保文档在更新期间不会更改。您可以使用 |
更新API不支持外部版本控制
更新API不支持外部版本控制(版本类型external
&external_gte
),因为这会导致Elasticsearch版本号与外部系统不同步。请改用 indexAPI。