弹性搜索,无痛脚本

时间:2018-09-20 19:14:48

标签: elasticsearch elasticsearch-painless

我正在尝试使用无痛方法来解决问题。我需要找到在指定日期范围内并按频率吃过任何指定食品的顾客数量。该代码适用于6.0,但适用于6.3
映射:

 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
 }
 }
 }
 }
 }
 }
 }

数据:

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"]
                }]
        }

查询:

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
                                    }
                                  }]}

                  }]}}}

查询在6.0中工作正常,在6.3中引发错误

Error:


    "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
}
}
}
]

文档中确实提到了重大更改

0 个答案:

没有答案