background

ElasticSearch is becoming more and more popular and is being used by many companies. Have done log search, have done commodity search, have done order search.

Most of the usage scenarios involve programs that periodically import data into ElasticSearch, or use CDC to build indexes. In this scenario, data is updated in a single mode. For example, if data whose ID is 1 is modified, data whose ID is 1 in ElasticSearch is updated.

Update Table Set Name=XXX where Age=18 Update Table Set Name=XXX where Age=18

ElasticSearch allows you to select conditional updates from ElasticSearch.

A single updating

ElasticSearch -rest-high-level-client is recommended for the ElasticSearch client. This article builds the code based on ElasticSearch – Rest-high-level client.

First, let’s review how to update a single piece of data. The code is as follows:

UpdateRequest updateRequest = new UpdateRequest(index, type, id);
updateRequest.doc(documentJson, XContentType.JSON);
restHighLevelClient.update(updateRequest, options);
Copy the code

When you build the UpdateRequest, you specify the index, type, and ID fields, so that the data is exactly the same as the updated data.

Conditional updates

First of all, we prepare several test data, as follows:

{id: 1, title: "How to learn Java", type: 1, userId: 1, tags: ["Java"], textContent: "I want to learn Java", status: 1, Heat: 100} {id: 2, title: "How to learn Java", type: 1, userId: 1, tags: ["Java"], textContent: "I want to learn Java", status: 1, Heat: 100}Copy the code

Suppose our requirement is to invalidate all document data for userId=1, that is, status=0. Without the conditional update, you would have to query all the data for userId=1 and then update it one by one, which would be too slow.

Let’s see how conditional updates are used, as follows:

POST to http://47.105.66.210:9200/article_v1/doc/_update_by_query {" script ": {" source" : "CTX. _source [' status'] = 0;" }, "query": { "term": { "userId": 1 } } }Copy the code

Conditional updates are performed using _update_by_query, which specifies the matching criteria for the updated data, and script for the update logic.

Detailed usage document:

https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html[1]

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html[2]

How do you implement conditional updates in Java code?

UpdateByQueryRequest request = new UpdateByQueryRequest("article_v1"); request.setQuery(new TermQueryBuilder("userId", 1)); request.setScript(new Script("ctx._source['status']=0;" )); restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);Copy the code

The update object is built using UpdateByQueryRequest and set up the Query and Script.

Conditional update array

For example, we need to remove Java from tags as follows:

POST to http://47.105.66.210:9200/article_v1/doc/_update_by_query {" script ": { "source":"ctx._source['tags'].removeIf(item -> item == 'java');" }, "query": { "term": { "userId": 1 } } }Copy the code

To add, just change removeIf to Add.

ctx._source['tags'].add('java');
Copy the code

If there is special business logic, Script can also write judgments to determine whether it needs to be modified.

POST to http://47.105.66.210:9200/article_v1/doc/_update_by_query {" script ": { "source":"if(ctx._source.type == 11) {ctx._source['tags'].add('java'); }" }, "query": { "term": { "userId": 1 } } }Copy the code

Encapsulate common condition updates

Updates in most scenarios are simple, either to update a value based on a field or to update multiple values. If you script everywhere in Java, you’re repeating yourself, and it’s best to pick a more generic way to update it.

Here’s a simple List. There are a lot of points to consider, like data types. I only dealt with numbers, strings, and lists.

public BulkByScrollResponse updateByQuery(String index, QueryBuilder query, Map<String, Object> document) { UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest(index); updateByQueryRequest.setQuery(query); StringBuilder script = new StringBuilder(); Set<String> keys = document.keySet(); for (String key : keys) { String appendValue = ""; Object value = document.get(key); if (value instanceof Number) { appendValue = value.toString(); } else if (value instanceof String) { appendValue = "'" + value.toString() + "'"; } else if (value instanceof List){ appendValue = JsonUtils.toJson(value); } else { appendValue = value.toString(); } script.append("ctx._source.").append(key).append("=").append(appendValue).append(";" ); } updateByQueryRequest.setScript(new Script(script.toString())); return updateByQuery(updateByQueryRequest, RequestOptions.DEFAULT); } public BulkByScrollResponse updateByQuery(UpdateByQueryRequest updateByQueryRequest, RequestOptions options) { Map<String, Object> catData = new HashMap<>(1); catData.put(ElasticSearchConstant.UPDATE_BY_QUERY_REQUEST, updateByQueryRequest.toString()); return CatTransactionManager.newTransaction(() -> { try { return restHighLevelClient.updateByQuery(updateByQueryRequest,  options); }catch (IOException e) { throw new RuntimeException(e); } }, ElasticSearchConstant.ES_CAT_TYPE, ElasticSearchConstant.UPDATE, catData); }Copy the code

If there is such a method, it can be used as follows:

@Test
public void testUpdate5() {
    Map<String, Object> document = new HashMap<>();
    document.put("title", "Java");
    document.put("status", 0);
    document.put("tags", Lists.newArrayList("JS", "CSS"));
    kittyRestHighLevelClient.updateByQuery(elasticSearchIndexConfig.getArticleSaveIndexName(), new TermQueryBuilder("userId", 1), document);
}
Copy the code

About the author: Yin Jihuan, a simple technology lover, the author of Spring Cloud Micro-service – Full stack Technology and Case Analysis, Spring Cloud Micro-service Introduction combat and Progress, the founder of the public account Monkey World.

The resources

[1]

docs-update-by-query.html: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html


[2]

modules-scripting-using.html: https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html

If you are interested, you can pay attention to my wechat public number, Simtiandi, and read more technical articles for the first time. I also have some open source code on GitHub github.com/yinjihuan