4

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 ?

4 Answers 4

5

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();
Sign up to request clarification or add additional context in comments.

2 Comments

Hey. In fact this solution is possible but the doc that I receive is always different so i can not hardcode it , and I tried a lot of methods with setDoc but none of them worked properly. Finally the script usage above was the solution of my problem
based on your example though, you had the json -- it would have just been json.toString().getBytes() instead of the hardcoded value... that avoids invoking a script which should make it faster overall.
4

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.

Comments

4

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.

1 Comment

for ( /*each namedEntity*/) { what will be this value?
1

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"
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.