Using doc_value returns error with update and _update_by_query in elasticsearch :: ScriptException[runtime error]; nested: NullPointerException (Elasticsearch 6.4)

The update gets committed when I use this query.

POST my_collegues_names/_update_by_query?error_trace=true
{
"script": {
"lang": "painless",
"source": "ctx._source.age +=params.last",
"params": {
"last": 5
}
},
"query": {
"match": {
"_id": 21
}
}
}

but I get error when I try to run this query.

POST my_collegues_names/_update_by_query?error_trace=true
{
"script_fields":{
"scriptname":{
"script": {
"lang": "painless",
"source": "doc['age']+=params.last",
"params": {
"last": 20
}
}
}
},
"query": {
"match": {
"_id": 21
}
}
}

Error_trace
ScriptException[runtime error]; nested: NullPointerException;\r\n\tat org.elasticsearch.painless.PainlessScript.convertToScriptException(PainlessScript.java:94)\r\n\tat org.elasticsearch.painless.PainlessScript$Script.execute(doc['age']= doc['age'] +params.last:4)\r\n\tat org.elasticsearch.painless.ScriptImpl.run(ScriptImpl.java:105)\r\n\tat org.elasticsearch.index.reindex.AbstractAsyncBulkByScrollAction$ScriptApplier.apply(AbstractAsyncBulkByScrollAction.java:819)\r\n\tat org.elasticsearch.index.reindex.AbstractAsyncBulkByScrollAction$ScriptApplier.apply(AbstractAsyncBulkByScrollAction.java:768)\r\n\tat org.elasticsearch.index.reindex.AbstractAsyncBulkByScrollAction.buildBulk(AbstractAsyncBulkByScrollAction.java:216)\r\n\tat org.elasticsearch.index.reindex.AbstractAsyncBulkByScrollAction.prepareBulkRequest(AbstractAsyncBulkByScrollAction.java:326)\r\n\tat org.elasticsearch.index.reindex.AbstractAsyncBulkByScrollAction$1.doRun(AbstractAsyncBulkByScrollAction.java:289)\r\n\tat org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:723)\r\n\tat org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)\r\n\tat org.elasticsearch.index.reindex.WorkerBulkByScrollTaskState$RunOnce.doRun(WorkerBulkByScrollTaskState.java:321)\r\n\tat org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)\r\n\tat org.elasticsearch.index.reindex.WorkerBulkByScrollTaskState$DelayedPrepareBulkRequest$1.doRun(WorkerBulkByScrollTaskState.java:257)\r\n\tat org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:723)\r\n\tat org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\nCaused by: java.lang.NullPointerException\r\n\tat org.elasticsearch.painless.PainlessScript$Script.execute(doc['age']= doc['age'] +params.last:17)\r\n\t... 16 more\r\n"

I am not able to understand why can't I use doc['age'] in my script.

Please help

Hi, is age a numeric field? You will want to use doc['age'].value (documentation).

Yes Jen,
age is an integer type.
I have used doc['age'].value but still get an error.
I have also modified the expression like

"source":"doc['age'].value =doc['age'].value+params.last",

but still facing the error

{
"error": {
"root_cause": [
{
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['age'].value =doc['age'].value+params.last",
" ^---- HERE"
],
"script": "doc['age'].value =doc['age'].value+params.last",
"lang": "painless"
}
],
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"doc['age'].value =doc['age'].value+params.last",
" ^---- HERE"
],
"script": "doc['age'].value =doc['age'].value+params.last",
"lang": "painless",
"caused_by": {
"type": "null_pointer_exception",
"reason": null
}
},
"status": 500
}

I am sorry, I misunderstood the intention of your original post. doc can't be used for updating documents, ctx._source needs to be used to refer to the source document. Since you already got it working with using ctx._source, is there another reason for using doc?

Yes, Actually Elasticsearch documentation says that doc_value is the most efficient way to access a field value from a script, and also they say that we should always prefer doc_value over stored fields such as _source(a special stored field) because they are must faster than stored fields when it comes to update a value of a specific field.
Scripting doc_values

Thanks for your reply Jen.

I understand; this is true for accessing a field via painless script. I just confirmed with the ES team that for updating a field with painless script, doc is not available, see: https://www.elastic.co/guide/en/elasticsearch/painless/6.4/painless-update-by-query-context.html

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.