Search code examples
elasticsearchnullpointerexceptionnestedkibana

Elasticsearch: Trying to loop a nested params.value in ctx._source gives null_pointer_exception


Im attempting to run the following elasticsearch-script in Kibana:

{
  "script": {
      "source": "for( nested in ctx._source.params.title_type){if (nested.id == params.id){ nested.title = params.new_title}}",
      "lang": "painless",
      "params": {
          "title_type": "categories",
          "id": "123",
          "new_title": "new title"
      }
  }
}

With the intention of updating the field source.categories.title to "new title", if source.categories.id = "123".

However when i attempt this i get the following error:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "illegal_argument_exception",
        "reason" : "failed to execute script"
      }
    ],
    "type" : "illegal_argument_exception",
    "reason" : "failed to execute script",
    "caused_by" : {
      "type" : "script_exception",
      "reason" : "runtime error",
      "script_stack" : [
        "for( nested in ctx._source.params.title_type){",
        "                                 ^---- HERE"
      ],
      "script" : "for( nested in ctx._source.params.title_type){if (nested.id == params.id){ nested.title = params.new_title}}",
      "lang" : "painless",
      "caused_by" : {
        "type" : "null_pointer_exception",
        "reason" : null
      }
    }
  },
  "status" : 400
}

This exact script works if i replace 'params.title_type' with hardcoded 'categories' like in this example:

{
  "script": {
      "source": "for( nested in ctx._source.categories){if (nested.id == params.id){ nested.title = params.new_title}}",
      "lang": "painless",
      "params": {
          "title_type": "categories",
          "id": "123",
          "new_title": "new title"
      }
  }
}

What am i doing wrong in the first example where im using a parameter (like i succesfully do other places in the script)?


Solution

  • ctx._source is a Map underneath, so you need to reference params.title_type differently, like this and it will work

    ctx._source[params.title_type]
    

    This will be equivalent of writing

    ctx._source["categories"]
    

    or

    ctx._source.categories