1

Using Elasticsearch 1.7.1, I have the following document structure

"_source" : {
"questions" : {
    "defaultQuestion" : {           
        "tag" : 0,
        "gid" : 0,
        "rid" : 0,
        "caption" : "SRID",         
    },
    "tableQuestion" : {
        "rows" : [{
                "ids" : {                       
                    "answerList" : ["3547", "3548"],                        
                    "tag" : "0",
                    "caption" : "Accounts",                     
                },
                "name" : {                      
                    "answerList" : ["Some Name"],                       
                    "tag" : "0",
                    "caption" : "Name",                     
                }
            }
        ],
        "caption" : "BPI 1500541753537",
        "id" : 644251570,
        "tag" : ""
    }
},
"id" : "447722821"  
}

I want to add a new object in in questions.tableQuestion.rows. My current script is replacing the existing object with the new one. Kindly suggest how to append it instead. Following is my update script.

{ "update": {"_id": "935663867", "_retry_on_conflict" : 3} }
{ "script" : "ctx._source.questions += param1", "params" : {"param1" : {"tableQuestion": {"rows" : [ NEWROWOBJECT ]}  } }}

1 Answer 1

2

You can build the path with next nested fields, right to the rows property and then use += operator. It's also good to have a check if rows array is null and initialize it in this case.

Checked with ES 2.4, but should be similar for earlier versions:

POST http://127.0.0.1:9200/sample/demo/{document_id}/_update

{ 
    "script": {
        "inline": "if (ctx._source.questions.tableQuestion.rows == null) ctx._source.questions.tableQuestion.rows = new ArrayList(); ctx._source.questions.tableQuestion.rows += param1;",
        "params" : {
            "param1" : {
                            "ids": {
                                "answerList": [
                                    "478",
                                    "255"
                                ],
                                "tag": "2",
                                "caption": "My Test"
                            },
                            "name": {
                                "answerList": [
                                    "My Name"
                                ],
                                "tag": "1",
                                "caption": "My Demo"
                            }
                        }
        }
    }
}

For ES 5.x and Painless language the script is a bit different:

POST http://127.0.0.1:9200/sample/demo/{document_id}/_update

{ 
    "script": {
        "inline": "if (ctx._source.questions.tableQuestion.rows == null) { ctx._source.questions.tableQuestion.rows = new ArrayList();} ctx._source.questions.tableQuestion.rows.add(params.param1);",
        "params" : {
            "param1" : {
                            ...
            }
        }
    }
}

Update to the additional comment

If some part of the path is dynamic, you can also use parameters to build the path - with get(param_name) method - try this syntax (I removed the null check for simplicity):

{ 
    "script": {
        "inline": "ctx._source.questions.get(param2).rows += param1;",
        "params" : {
            "param2" : "6105243",
            "param1" : {
                            "ids": {
                                "answerList": [
                                    "478",
                                    "255"
                                ],
                                "tag": "2",
                                "caption": "My Test"
                            },
                            "name": {
                                "answerList": [
                                    "My Name"
                                ],
                                "tag": "1",
                                "caption": "My Demo"
                            }
                        }
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I tried it earlier but it failed as the actual data contains a numeric ID instead of 'tableQuestion'. Any workaround if the data structure is "6105243" : {"rows" : [{"ids":{"answerList":["3547","3548"],"tag":"0","caption":"Accounts"}}] } Thanks for the help
If I understand you correctly - instead of tableQuestion you have a dynamic ID. I updated my answer, hope it can help to solve the case.
@Joanna sorry for bothering you on this old topic. But will this still work in ES 6.x because I'm getting errors like "Illegal list shortcut value" which means that I want to reach an inner nested of my principal nested (and it is not possible apparently)

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.