Update nested field in an index of ElasticSearch with Java API

10,847

Solution 1

I tried to recreate your situation and i solved it by using an other way the .setScript method.

Your updating request now would looks like :

client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location =" + json).execute().actionGet()

Hope it will help you.

Solution 2

You don't need the script, just update it.

    UpdateRequestBuilder br = client.prepareUpdate("index", "enduser", "1");
    br.setDoc("{\"location\":{ \"name\": \"london\", \"point\": \"44.5,5.2\" }}".getBytes());
    br.execute();

Solution 3

I am not sure which ES version you were using, but the below solution worked perfectly for me on 2.2.0. I had to store information about named entities for news articles. I guess if you wish to have multiple locations in your case, it would also suit you.

This is the nested object I wanted to update:

"entities" : [
    {
        "disambiguated" : {
            "entitySubTypes" : [],
            "disambiguatedName" : "NameX"
        },
        "frequency" : 1,
        "entityType" : "Organization",
        "quotations" : ["...", "..."],
        "name" : "entityX"
    },
    {
        "disambiguated" : {
            "entitySubType" : ["a",  "b" ],
            "disambiguatedName" : "NameQ"
        },
        "frequency" : 5,
        "entityType" : "secondTypeTest",
        "quotations" : [ "...", "..."],
        "name" : "entityY"
    }
],

and this is the code:

UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index(indexName);
updateRequest.type(mappingName);
updateRequest.id(url); // docID is a url
XContentBuilder jb = XContentFactory.jsonBuilder();
jb.startObject(); // article
jb.startArray("entities"); // multiple entities

for ( /*each namedEntity*/) {

jb.startObject() // entity
   .field("name", name)
   .field("frequency",n)
   .field("entityType", entityType)
   .startObject("disambiguated") // disambiguation
   .field("disambiguatedName", disambiguatedNameStr)
   .field("entitySubTypes", entitySubTypeArray) // multi value field
   .endObject() // disambiguation
   .field("quotations", quotationsArray) // multi value field
   .endObject(); // entity

}

jb.endArray(); // array of nested objects
b.endObject(); // article
updateRequest.doc(jb);

Blblblblblblbl's answer couldn't work for me atm, because scripts are not enabled in our server. I didn't try Bask's answer yet - Alcanzar's gave me a hard time, because I supposedly couldn't formulate the json string correctly that setDoc receives. I was constantly getting errors that either I am using objects instead of fields or vice versa. I also tried wrapping the json string with doc{} as indicated here, but I didn't manage to make it work. As you mentioned it is difficult to understand how to formulate a curl statement at ES's java API.

Solution 4

A simple way to update the arraylist and object value using Java API.

UpdateResponse update = client.prepareUpdate("indexname","type",""+id)
        .addScriptParam("param1", arrayvalue)
         .addScriptParam("param2", objectvalue)
        .setScript("ctx._source.field1=param1;ctx._source.field2=param2").execute()
                .actionGet(); 

arrayvalue-[
{
    "text": "stackoverflow",
    "datetime": "2010-07-27T05:41:52.763Z",
    "obj1": {
        "id": 1,
        "email": "[email protected]",
        "name": "bass"
        },
    "id": 1,
}

object value -
"obj1": {
    "id": 1,
    "email": "[email protected]",
    "name": "bass"
}
Share:
10,847
razafinr
Author by

razafinr

Updated on June 18, 2022

Comments

  • razafinr
    razafinr almost 2 years

    I am using Java API for CRUD operation on elasticsearch.

    I have an typewith a nested field and I want to update this field.

    Here is my mapping for the type:

    "enduser": {
                "properties": {
                    "location": {
                        "type": "nested",
                        "properties":{
                            "point":{"type":"geo_point"}
                        }
                    }
                }
            }
    

    Of course my enduser type will have other parameters.

    Now I want to add this document in my nested field:

    "location":{
              "name": "London",
               "point": "44.5, 5.2"
    }
    

    I was searching in documentation on how to update nested document but I couldn't find anything. For example I have in a string the previous JSON obect (let's call this string json). I tried the following code but seems to not working:

    params.put("location", json);
    client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location = location").setScriptParams(params).execute().actionGet();
    

    I have got a parsing error from elasticsearch. Anyone knows what I am doing wrong ?