Stored fields with array ,painless scripting throwing NPE


(Nagabhushanam Katikireddi) #1

I am trying to solve a problem using painless. I need to find number of customers who ate any of the specified food items within specified date range and with frequency . The code works on 6.0 but breaks on 6.3.
Below is my Mapping

PUT  myindex
        		{
        		"settings": {
        		"index": {
        		"number_of_shards": 2
        		}
        		},
        		"mappings": {
        		"customer": {
        		"dynamic": "strict",
        		"properties": {
        		"customerName": {
        		"type": "keyword"
        		},
        		"customerRegion": {
        		"type": "keyword"
        		},
        		"dateOfBirthYear": {
        		"type": "date",
        		"format": "yyyy"
        		},
        		"foods": {
        		"properties": {
        		"dates": {
        		"type": "date",
        		"index": false,
        		"store": true,
        		"ignore_malformed": true,
        		"format": "yyyy-MM-dd"
        		},
        		"datesCount": {
        		"type": "integer",
        		"index": false,
        		"store": true
        		},
        		"foodRowKey": {
        		"type": "keyword",
        		"index": false,
        		"store": true
        		}		}		}		}		}		}		}

Data is :
    PUT myindex/customer/1?refresh=true
            {
            "customerName" : "Batman",
            "customerRegion": "N California",
            "dateOfBirthYear" :"1977",
            "foods":[{
            			"foodRowKey": "Chicken",
            			"datesCount": 2,
            			"dates": ["2016-06-20"]
            		},{
            			"foodRowKey": "Soup",
            			"datesCount": 3,
            			"dates": ["2016-04-18", "2016-04-19", "2016-04-20"]
            		},{
            			"foodRowKey": "Dessert",
            			"datesCount": 3,
            			"dates": ["2016-06-20"]
            		}]
            }

        PUT myindex/customer/2?refresh=true
        {
        "customerName" : "Keenu Reeves",
        "customerRegion": "N California",
        "dateOfBirthYear" :"1987",
        "foods":[{
        			"foodRowKey": "Soup",
        			"datesCount": 1,
        			"dates": ["2016-06-20"]
        		},{
        			"foodRowKey": "Dessert",
        			"datesCount": 2,
        			"dates": ["2016-06-21","2016-08-12"]
        		},{
        			"foodRowKey": "Burger",
        			"datesCount": 2,
        			"dates": ["2016-06-20","2016-09-2"]
        		}]
        }

Query is :

            GET myindex/_search
            {
             "size" : 1000,
                "query" : {
                  "bool" : {
                    "filter" : [
                      {
                        "bool" : { "must":[{ "script" : {
                                          "script" : {
                                            "lang": "painless",
                                            "source" : "def fromDt = LocalDate.parse(params.fromDate); def toDt = LocalDate.parse(params.toDate); def rowKeys = params._fields[params.rowKeyField].values; def dates = params._fields[params.dateField].values; def dateCounts = params._fields[params.dateCountField].values; def interestingDates = new HashSet(); def datesCtr = 0; if (dateCounts.size() < params.min_occurs) { return (false); } for (int ctr = 0; ctr < rowKeys.size(); ctr++) { if (params.rowKey.contains(rowKeys.get(ctr))) { def matchingDates = dates.subList(datesCtr, datesCtr + dateCounts.get(ctr).intValue()); if (matchingDates.size() < params.min_occurs) { break; } for (int ctr1 = 0; ctr1 < matchingDates.size(); ctr1++) { def dt = LocalDate.parse(matchingDates.get(ctr1)); if (dt.isAfter(toDt)) { break; } else if (dt.isAfter(fromDt) && dt.isBefore(toDt)) { interestingDates.add(dt); } else if (dt.equals(fromDt) || dt.equals(toDt)) { interestingDates.add(dt); } } if (interestingDates.size() >= params.min_occurs && ChronoUnit.DAYS.between(Collections.min(interestingDates), Collections.max(interestingDates)) >= params.gapDays) { return (true); } } datesCtr += dateCounts.get(ctr).intValue(); }",
                                            "params" : {
                                              "fromDate" : "2016-04-01",
                                              "dateCountField" : "foods.datesCount",
                                              "min_occurs" : 2,
                                              "rowKeyField" : "foods.foodRowKey",
                                              "toDate" : "2016-06-30",
                                              "dateField" : "foods.dates",
                                              "rowKey" : [
                                                "Soup","Dessert"],
                                              "gapDays" : 0
                                            }
                                          },
                                          "boost" : 1.0
                                        }       }]}                    }]}}}

Below is the error stack trace

 "failures": [
      {
"shard": 1,
"index": "myindex",
"node": "NZXRtCJDRxOpaYk-dvD3FA",
"reason": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"rowKeys = params._fields[params.rowKeyField].values; def ",
" ^---- HERE"
],
"script": "def fromDt = LocalDate.parse(params.fromDate); def toDt = LocalDate.parse(params.toDate); def rowKeys = params._fields[params.rowKeyField].values; def dates = params._fields[params.dateField].values; def dateCounts = params._fields[params.dateCountField].values; def interestingDates = new HashSet(); def datesCtr = 0; if (dateCounts.size() < params.min_occurs) { return (false); } for (int ctr = 0; ctr < rowKeys.size(); ctr++) { if (params.rowKey.contains(rowKeys.get(ctr))) { def matchingDates = dates.subList(datesCtr, datesCtr + dateCounts.get(ctr).intValue()); if (matchingDates.size() < params.min_occurs) { break ; } for (int ctr1 = 0; ctr1 < matchingDates.size(); ctr1++) { def dt = LocalDate.parse(matchingDates.get(ctr1)); if (dt.isAfter(toDt)) { break; } else if (dt.isAfter(fromDt) && dt.isBefore(toDt)) { interestingDates.add(dt); } else if (dt.equals(fromDt) || dt.equals(toDt)) { interestingDates.add(dt); } } if (interestingDates.size() >= params.min_occurs && ChronoUnit.DAYS.between(Collections.min(interestingDates), Collections.max(interestingDates)) >= params.gapDays) { return (true); } } datesCtr += dateCounts.get(ctr).intValue(); }",
"lang": "painless",
"caused_by": {
"type": "null_pointer_exception",
"reason": null    }  }    }    ]

(Ryan Ernst) #2

The error you get doesn't seem to match with the script you have pasted here. The script in the exception starts with rowKeys = params._fields[params.rowKeyField].values; def, while the script in the example request starts with def fromDt = LocalDate.parse(params.fromDate);. Just looking at the exception, it looks like def is in the wrong place, but I would not expect an unknown variable to cause an NPE.


(Nagabhushanam Katikireddi) #3

any help here


(system) #4

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