1

I'm trying to make a select query with a Painless script, but I keep getting an error in the response that the script is not valid.

What I'm trying to do in this simplified script is to check if my given param ages are both adult following the age in 'unit.info'.

Error:

    "if(containsAge(doc['unitHolder.units'], params.ages)){",
    "                   ^---- HERE",...
"caused_by": {
      "type": "illegal_argument_exception",
      "reason": "No field found for [unitHolder.units] in mapping with types [pack]"
      }

Request query:

    {
        "query": {
            "bool": {
                "must": [
                    {
                        "script": {
                            "script": {
                                "source": "boolean containsAge(def unit, def ages) 
                                {
                                    if(unit.info.children.minAge != null)
                                    {
                                        int nrAdults = 0;
                                        int nrChildren = 0;
                                        int nrInfants = 0;

                                        for (age in ages)
                                        {
                                            if (age < unit.info.children.maxAge.value)
                                            {
                                                nrAdults++;
                                            }else if(age > unit.info.children.minAge.value)
                                            {
                                                nrInfants++;
                                            }else{
                                                nrChildren++;
                                            }
                                        }
                                        if (nrAdults > 2)
                                        {
                                            return true;
                                        }
                                    }
                                    return false;
                                }
                                if(containsAge(doc['unitHolder.units'], params.ages))
                                {
                                    return true;
                                }
                                return false;",
                                "lang": "painless",
                                "params": {
                                    "ages": [
                                        50,
                                        35
                                    ]
                                }
                            }
                        }
                    }
                ]
            }
        },
        "size": 10
    }

Mapping:

"mappings": {
    "pack": {
        "properties": {
            "unitHolder": {
                "properties": {
                    "createDate": {
                        "type": "date"
                    },
                    "units": {
                        "properties": {
                            "info": {
                                "properties": {
                                    "children": {
                                        "properties": {
                                            "maxAge": {
                                                "type": "long"
                                            },
                                            "minAge": {
                                                "type": "long"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
BvdVen
  • 2,921
  • 23
  • 33

1 Answers1

3

This is because doc[<fieldName>] accesses doc-values, so it doesn't work on nested structures. From Elasticsearch documentation:

"Doc-values can only return "simple" field values like numbers, dates, geo- points, terms, etc, or arrays of these values if the field is multi-valued. It can not return JSON objects."

What you need is to put params._source[unitHolder] into a Map-type variable and then see if that variable contains unit.

Updated to incl some example:

Map unitHolderMap = params._source['unitHolder`];
if (unitHolderMap.containsKey('units')){
    // get the ages from their respective properties and evaluate them
}
SylarBenes
  • 411
  • 3
  • 7
  • Ok, so Doc only works with simple types, I get that. But I don't understand what you mean to put unitHolder into a Map-Type variable, I thought the mapping items only can be simpletypes, so how would I be able to put an array of objects in the mapping? – BvdVen Oct 31 '19 at 14:00
  • Not in the mapping. In the painless script you can declare a variable, and because you declare it as a Map, you will be able to use corresponding functions. Will update my answer with some pseudo code – SylarBenes Oct 31 '19 at 14:07
  • Thanks for the info, I tried this, but I get a null_pointer_exception on "params._source". I'm using the script in a query, so not in a update or sort (I believe that might make a difference) – BvdVen Oct 31 '19 at 14:17
  • You're right the operation can make a difference, but for me it works on query. Maybe the field is null on some doc? You could try `(if unitHolderMap ! = null) { if (unitHolderMap.containsKey('units')) {` . What ES version are you using? – SylarBenes Oct 31 '19 at 15:13
  • Currently running 6.8.0, but just tested on 7.4.0 with the same result. And it's not failing on the unitHolderMap value but on the params._source it seems. – BvdVen Oct 31 '19 at 15:49
  • It seems like params['_source'] is always NULL, but there are documents in the index. – BvdVen Oct 31 '19 at 15:54
  • Ok, we're stil at 6.5. and I see they changed the documentation a bit, so what works for me probably doesn't work for you. You could try replacing `params._source['unitHolder']` with `_source.unitHolder` . – SylarBenes Oct 31 '19 at 15:56