Querying and sorting using painless script and nested fields

Hi,

I am querying an index in my ES cluster 7.9.1:

{
   "query": {
      "multi_match": {
         "query": "Ciudad Boli",
         "fields": [
            "name.*.single"
         ],
         "type": "phrase_prefix"
      }
   },
   "sort": [
      {
         "_script": {
            "script": {
               "source": "_score * (doc.containsKey('sales.countries.CO.products.HOTELS.total') ? (1.0 + doc['sales.countries.CO.products.HOTELS.total'].value) : 0.0)",
               "lang": "painless"
            },
            "type": "number",
            "order": "desc"
         }
      }
   ],
   "track_scores": true
}

Some documents have an object "sales", with a property "countries", with a property "CO" and so on so on.. but other documents not. The idea is sort the results according this data.
But I'm getting this error:

{
    "error": {
        "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)",
                    "_score * (doc.containsKey('sales.countries.CO.products.HOTELS.total') ? (1.0 + doc['sales.countries.CO.products.HOTELS.total'].value) : 0.0)",
                    "                                                                                                                              ^---- HERE"
                ],
                "script": "_score * (doc.containsKey('sales.countries.CO.products.HOTELS.total') ? (1.0 + doc['sales.countries.CO.products.HOTELS.total'].value) : 0.0)",
                "lang": "painless",
                "position": {
                    "offset": 126,
                    "start": 0,
                    "end": 140
                }
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
            {
                "shard": 0,
                "index": "cities",
                "node": "Jxy454W0S-mxTongRFYWOw",
                "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)",
                        "_score * (doc.containsKey('sales.countries.CO.products.HOTELS.total') ? (1.0 + doc['sales.countries.CO.products.HOTELS.total'].value) : 0.0)",
                        "                                                                                                                              ^---- HERE"
                    ],
                    "script": "_score * (doc.containsKey('sales.countries.CO.products.HOTELS.total') ? (1.0 + doc['sales.countries.CO.products.HOTELS.total'].value) : 0.0)",
                    "lang": "painless",
                    "position": {
                        "offset": 126,
                        "start": 0,
                        "end": 140
                    },
                    "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!"
                    }
                }
            }
        ]
    },
    "status": 400
}

Can anybody help me please?

Hey,

the exception already states a workaround, that you should include in your script, because you seem to have documents, where the field that you are referring to does not exist.

--Alex

Thanks for your reply...

Yes, that's the key. I thought that checking doc.containsKey(...) was enough, but I was wrong.
Later I found in the documentation:

The doc['field'] will throw an error if field is missing from the mappings. In painless , a check can first be done with doc.containsKey('field') to guard accessing the doc map.

Finally, using both checks works for me:
if(doc.containsKey(key) && doc[key].size()>=1.0) {

Thanks!

2 Likes

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