一、前言
最近发现要经常根据查询条件来更新字段的值,公司的es有5.6 6.8 7.8这3个版本,之前是将数据查询出来,修改好其中的值,然后再保存进es的,感觉这样很费事。
由于用的是es原生Java API,又要支持多个版本的es,所以只能自己写代码了。
如果用Spring Data ES的话,那里面的方法很全面很方便,可惜公司的并不用。
二、ES5.6 Java API的实现
ES5.6 Java API的Low Level实现,通过测试,链接ES5.6 ES6.8使用都可以。
public static void updateByQuery(String index, String type, QueryBuilder query, String strScript) {
String method = "POST";
String endpoint = "/" + index + "/" + type + "/_update_by_query?conflicts=proceed";
if (query != null) {
String queryString = "{"
+ " \"script\": { "
+ " \"source\": " + "\"" + strScript + "\""
+ "},"
+ " \"query\": " + query.toString()
+ "}";
HttpEntity entity = new NStringEntity(queryString, ContentType.APPLICATION_JSON);
Map<String, String> params = Collections.emptyMap();
try {
restClient.performRequest(method, endpoint, params, entity);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
三、ES6.8 Java API的实现
ES6.8 Java API的High Level的API已经很丰富了。
public static BulkByScrollResponse updateByQuery(String index, String type, QueryBuilder query, String strScript) {
BulkByScrollResponse bulkResponse = null;
try {
UpdateByQueryRequest request =
new UpdateByQueryRequest(index);
request.setDocTypes(type);
request.setConflicts("proceed");
request.setQuery(query);
Script script = new Script(
ScriptType.INLINE, "painless",
strScript,
Collections.emptyMap());
request.setScript(script);
bulkResponse =
restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("ES更新异常", e.getMessage());
}
return bulkResponse;
}
调用代码如下:
IdsQueryBuilder idsQueryBuilder = QueryBuilders.idsQuery().addIds(ids.stream().toArray(String[]::new));
KawfRestfulElasticsearchUtils.updateByQuery(
"pigg_test",
"pigg_test",
idsQueryBuilder,
"ctx._source['pttStatus']='1'"
);