Painless: problem accessing nested object using dot notation



I'm having problems reindexing data using a painless script.

The nested field is mapped as an object in the destination index, but in some cases the source data is either a string or an array of longs

The script attempts to:

  1. Check if the field exists
  2. Check the field's type
  3. If it is a string or array
    • create a temporary string / array variable
    • assign the value of the offending field to this variable
    • change the value of the field to be a new object (passed in via params) using a put command
    • assign the value of the temp variable to the first key/value pair of the new object

This works fine for strings, but it's not working for arrays.

Here's one document it fails on:

    "_index": "logstash-crm-2018.04.29",
    "_type": "doc",
    "_id": "ssNuEGMBPRb2-UEOO0NF",
    "_version": 1,
    "found": true,
    "_source": {
        "context": {
            "data": {
                "result": [
                "resultCount": 3
            "message": "success",
            "status": 200
        "type": "log",
        "level": 200,
        "log_type": "json",
        "source": "/var/www/our-crm/log/our-crm-2018-04-29.log",
        "datetime": {
            "timezone_type": 3,
            "date": "2018-04-29 09:04:08",
            "timezone": "Europe/London"
        "@version": "1",
        "level_name": "INFO",
        "tags": [
        "@timestamp": "2018-04-29T08:04:09.437Z",
        "input_type": "log",
        "service": "crm",
        "offset": 82722,
        "beat": {
            "version": "5.6.8",
            "name": "aws-hostname",
            "hostname": "aws-hostname"
        "log_source": "file"

And here's my Painless script:

  "source": {
    "index": ["{{source}}"]
  "dest": {
    "index": "{{dest}}"
  "script": {
    "source": """
    if (ctx._source.context != null) {
        if (ctx._source.context instanceof String) {
            String name = ctx._source.context;
            ctx._source.put(\"context\", params.context);
   = name 
        } else if ( != null) {
            if ( instanceof Long) {
                Long number =;
                ctx._source.put(\"\", params.result);
       = number 
            } else if ( instanceof List) {
                    long[] longArray = new long[];
                    longArray =;
                    ctx._source.put(\"\", params.result2);
           = longArray 
    "lang": "painless",
     "params": {
     "context": { "name": "blank" },
     "result": { "number": 1234 },
     "result2": { "longArray": [1234, 5678] }

Currently Painless throws an error at this point in the code:

            "if ( != null) {",
            "                       ^---- HERE"

And the error message is:

            "type": "illegal_argument_exception",
            "reason": "Illegal list shortcut value [data]."

I'm not sure why this would be the case, since I know the source data contains

(Ryan Ernst) #2

It looks like ctx._source.context is an array in your source. So you need to iterate through each value of the array and dereference it by index. So instead of, you need a loop like:

for (int i = 0; i < ctx._source.context.length; ++i) {


Hi Ryan, thanks for your reply!

result is definitely an array but context is an object, unless I'm misunderstanding something?

(Ryan Ernst) #4

Are you sure all of your documents have context as an object? The error from painless indicates it found a List.

(system) #5

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