Unable to create scripted field

Hello,

Elastic version: 7.9.1
Kibana version: 7.9.0

I am struggling to create a scripted field. To put it on perspective, I have the field "apache.status.total_kbytes". And I would like to create a scripted field named "apache.status.total_mbytes".

Mapping of apache.status.total_kbytes:

  "metricbeat-7.9.2-2020.10.14-000001" : {
    "mappings" : {
      "apache.status.total_kbytes" : {
        "full_name" : "apache.status.total_kbytes",
        "mapping" : {
          "total_kbytes" : {
            "type" : "long"
          }
        }
      }
    }
  }

In order to do so, I created a scriped field in kibana, using the following code:

if (doc.containsKey('apache.status.total_kbytes')){
    long kb=doc['apache.status.total_kbytes'].value;
    return kb/1024L;
}
return null;

When I enter into kibana I see the following error

Am I missing something? Why can't I access the "value" attribute of the document field?

Thanks in advance!

I guess something like this may help

if (doc.containsKey('apache.status.total_kbytes') && doc['apache.status.total_kbytes'].size() != 0){
    long kb=doc['apache.status.total_kbytes'].value;
    return kb/1024L;
}

The full error was : A document doesn't have a value for a field! Use doc[].size()==0 to check if a document is missing a field!

{
 "root_cause": [
  {
   "type": "script_exception",
   "reason": "runtime error",
   "script_stack": [
    "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
    "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
    "kb=doc['apache.status.total_kbytes'].value;\r\n    ",
    "                                    ^---- HERE"
   ],
   "script": "if (doc.containsKey('apache.status.total_kbytes')){\r\n    long kb=doc['apache.status.total_kbytes'].value;\r\n    return kb/1024L;\r\n}\r\nreturn null;",
   "lang": "painless",
   "position": {
    "offset": 98,
    "start": 62,
    "end": 111
   }
  }
 ],
 "type": "search_phase_execution_exception",
 "reason": "all shards failed",
 "phase": "query",
 "grouped": true,
 "failed_shards": [
  {
   "shard": 0,
   "index": "metricbeat-7.9.2-2020.09.26-000001",
   "node": "1ksZhfyPR2my8OyC5uuVSQ",
   "reason": {
    "type": "script_exception",
    "reason": "runtime error",
    "script_stack": [
     "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
     "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
     "kb=doc['apache.status.total_kbytes'].value;\r\n    ",
     "                                    ^---- HERE"
    ],
    "script": "if (doc.containsKey('apache.status.total_kbytes')){\r\n    long kb=doc['apache.status.total_kbytes'].value;\r\n    return kb/1024L;\r\n}\r\nreturn null;",
    "lang": "painless",
    "position": {
     "offset": 98,
     "start": 62,
     "end": 111
    },
    "caused_by": {
     "type": "illegal_state_exception",
     "reason": "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
    }
   }
  }
 ]
}
return null;
1 Like

Okay it worked. My question now would be... why do I need to add the condition doc['apache.status.total_kbytes'].size() != 0 if I already check if the field exists within the dictionary via the condition: doc.containsKey('apache.status.total_kbytes')

Why do I have to do it explicitely like this doc['apache.status.total_kbytes'].size() != 0

I hope I explained myself.

Thanks!

The better is to use if (!doc['apache.status.total_kbytes'].empty) { ... }

The breaking change was mentionned here

Thank you very much Yassine!

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