这个系列的文章会基于Java描述Elasticsearch中主要API的用法,其中会加入一些自己的理解,如有错误之处还请不宁赐教,非常感谢。已经发布的文章在笔者有所感悟后还会不断更新,以期记录自己学习Elasticsearch的过程。
Elasticsearch更新文档
- Elasticsearch系列文档
- 前言
- 1 通过文档id更新文档
- 1.1 创建请求
- 1.2 构建更新内容
- 1.3 可选参数
- 1.3.1 冲突重试次数
- 1.3.2 允许返回文档
- 1.3.3 脚本upsert
- 1.3.4 更新视为upsert
- 1.4 执行请求
- 1.5 请求响应
- 2 通过查询条件更新文档
- 2.1 创建请求
- 2.2 可选参数
- 2.2.1 冲突策略
前言
JavaAPI下的Elasticsearch用法。
1 通过文档id更新文档 1.1 创建请求UpdateRequest request = new UpdateRequest(
"posts",
"1");
1.2 构建更新内容
可以使用内联脚本更新部分文档。如下将字段field 的值加上4。生产环境不推荐使用脚本,不方便排错和维护,并且影响操作性能。
Mapparameters = singletonMap("count", 4); Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.field += params.count", parameters); request.script(inline);
也可以使用一般方法更新部分文档。如下分别使用json、Map、XContentBuilder 和键值对构建更新内容。如果要更新的文档存在,这部分文档会被合并进去。
UpdateRequest request = new UpdateRequest("posts", "1");
String jsonString = "{" +
""updated":"2017-01-01"," +
""reason":"daily update"" +
"}";
request.doc(jsonString, XContentType.JSON);
MapjsonMap = new HashMap<>(); jsonMap.put("updated", new Date()); jsonMap.put("reason", "daily update"); UpdateRequest request = new UpdateRequest("posts", "1") .doc(jsonMap);
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.timeField("updated", new Date());
builder.field("reason", "daily update");
}
builder.endObject();
UpdateRequest request = new UpdateRequest("posts", "1")
.doc(builder);
UpdateRequest request = new UpdateRequest("posts", "1")
.doc("updated", new Date(),
"reason", "daily update");
如果要更新的文档不存在,可以添加一些内容来创建新文档,这个操作叫upsert。如下,要更新的文档不存在,则创建一个新文档并插入jsonString 中的内容。
String jsonString = "{"created":"2017-01-01"}";
request.upsert(jsonString, XContentType.JSON);
1.3 可选参数
1.3.1 冲突重试次数
如果在写入更新内容之前文档被改动了,更新操作会重试多少次。默认为0,即出现冲突不会重试。
request.retryOnConflict(3);1.3.2 允许返回文档
更新操作会返回受影响的文档,默认为false,即不返回。
request.fetchSource(true);
这个选项也可以返回或排除指定字段
String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(
new FetchSourceContext(true, includes, excludes));
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
request.fetchSource(
new FetchSourceContext(true, includes, excludes));
1.3.3 脚本upsert
无论要更新的文档不存在,脚本依然会执行并且会创建出新文档。
request.scriptedUpsert(true);1.3.4 更新视为upsert
更新部分文档时,如果要更新的文档不存在,则视为使用upsert方法,即不存在则创建新的文档。
request.docAsUpsert(true);1.4 执行请求
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
1.5 请求响应
updateResponse.getResult()可以返回文档是被创建、更新、删除还是这次更新没有改变任何文档,即你的更新内容和原内容本来就是一致的。
String index = updateResponse.getIndex();
String id = updateResponse.getId();
long version = updateResponse.getVersion();
if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {
} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {
}
如果设置了request.fetchSource(true),还可以获取到被更新的文档。result.isExists()在默认情况下是false,因为这时有request.fetchSource(false)。
GetResult result = updateResponse.getGetResult();
if (result.isExists()) {
String sourceAsString = result.sourceAsString();
Map sourceAsMap = result.sourceAsMap();
byte[] sourceAsBytes = result.source();
} else {
}
如果要更新的文档不存在,则可以用try catch捕获这个异常。
UpdateRequest request = new UpdateRequest("posts", "does_not_exist")
.doc("field", "value");
try {
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
}
}
2 通过查询条件更新文档
2.1 创建请求
同样可以一次更新多个index
UpdateByQueryRequest request =
new UpdateByQueryRequest("source1", "source2");
当您通过查询请求提交更新时,Elasticsearch 会先生成索引的快照,并使用内部版本号进行匹配。 当版本匹配时,更新文档并增加版本号。 如果在生成快照和处理更新操作之间文档发生更改,则会导致版本冲突并且操作失败。 你可以通过设置request.setConflicts(“proceed”)来计算版本冲突,从而避免操作停止和返回。 请注意,如果您选择计算版本冲突,则该操作可能会尝试从源更新比 max_docs 更多的文档,直到它成功更新了 max_docs 文档,或者它已经遍历了源查询中的每个文档。
2.2 可选参数 2.2.1 冲突策略request.setConflicts("proceed")
当使用查询请求提交更新时,Elasticsearch 会先生成索引的快照,并使用内部版本号进行匹配。 当版本匹配成功时,Elasticsearch 更新文档并增加版本号。 如果在生成快照和处理更新操作之间文档发生更改,则会导致版本冲突并且操作失败。
这时你可以通过设置request.setConflicts(“proceed”)来计数版本冲突,这样可以避免操作停止并返回。
后面的内容和《Elasticsearch删除文档》那边的差球不多,同样也是使用多重搜索获取到匹配的文档,再使用批量更新写入要更新的内容。后面多余的就不写了。



