arpit joshi
arpit joshi

Reputation: 2134

Update ElasticSearch document based on condition using Java API

I have a elasticsearch index (lets name it student) . I have the fields

{ "name","division" ,"class" , "studentRollNo"} .

Is it possible to to update elasticsearch index for on record whose name would be "ABC" . With update API I can only update it by id ,with Update with query how can I pass the jsonString . Lets say My json String for update would be

Existing :

{ "name":"abc" , "division":"D","class" :10 ,"studentRollNo":23}

To Update :

{"name":"abc" , "division" : A , "class" : 11 , "studentRollNo" : 23}

Upvotes: 1

Views: 2545

Answers (2)

tempEngineer
tempEngineer

Reputation: 233

Since there is no good official support or examples for ES 8.x version Adding snippet for that as well which i tried and worked (this is for 8.4.3)

SSLContext sslContext = getSSLContext();

BasicCredentialsProvider credsProv = new BasicCredentialsProvider();

credsProv.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username,password));
    
RestClient restClient = RestClient.builder(new HttpHost(host, port, port == 443 ? "https" : "http"))
                                                .setHttpClientConfigCallback(hc -> hc.setSSLContext(sslContext).setDefaultCredentialsProvider(credsProv))
                                                  .build();
    
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

ElasticsearchClient elasticsearchClient = new ElasticsearchClient(transport);



UpdateByQueryRequest.Builder builder = new UpdateByQueryRequest.Builder();

        builder.query(getBoolQuery()._toQuery()); // it will be of type BoolQuery.of(query -> { ... })._toQuery()

        InlineScript inlineScript = new InlineScript.Builder()
                .lang("painless")
                .source(getScriptSourceV8()) // it will be string type like "ctx._source=params";
                .params(getScriptParamsV8()) // it will be map of <String, JsonData>
                .build();

        Script script = new Script.Builder()
                .inline(inlineScript)
                .build();
        builder.script(script);

        builder.index("esIndex");
        builder.preference("_shards:"+shard);
        builder.timeout(new Time.Builder().time(TIMEOUT_UPDATE_BY_QUERY+"s").build());
        builder.conflicts(Conflicts.Proceed);

        UpdateByQueryResponse response = elasticsearchClient.updateByQuery(builder.build());

Upvotes: 0

Sagar Patel
Sagar Patel

Reputation: 5486

I am not sure which elasticsearch version you are using but below is code snippet for ES 7.13 version.

RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http")));

    UpdateByQueryRequest request = new UpdateByQueryRequest("student");
    request.setQuery(new TermQueryBuilder("name", "abc"));

    // This data map you can directly create from JSON string as well.
    Map<String, Object> data = new HashMap<String, Object>();
    data.put("name", "abc");
    data.put("division", "A");
    data.put("class", 11);
    data.put("studentRollNo", 23);

    Map<String, Object> param = new HashMap<String, Object>();
    param.put("data", data);

    // script will read data param value and assign to document source
    String source = "ctx._source=params.data";
    Script script = new Script(ScriptType.INLINE, "painless", source, param);

    request.setScript(script);
    client.updateByQuery(request, RequestOptions.DEFAULT);
    client.close();

Below is equivalent update by query rest API json:

POST student/_update_by_query
{
  "query": {
    "term": {
      "name": {
        "value": "abc"
      }
    }
  },
  "script": {
    "source": "ctx._source=params.data",
    "params": {
      "data": {
        "name": "abc",
        "division": "A",
        "class": 11,
        "studentRollNo": 23
      }
    }
  }
}

Upvotes: 3

Related Questions