最近在做脚本重评分时,遇上了一个空值问题。查询时painless脚本中若遇到字段中的值为空值就会报错,本来想用 value == null 这种形式的判断来判断字段值是否为空,然后过来掉,结果发现并不行,
以下时错误示范:
这个重评分的代码在defprice字段全部都有值得时候运行正常,但是一旦出现没有值得情况,就会报以下错误
{ "error": { "root_cause": [{ "type": "script_exception", "reason": "runtime error", "script_stack": [ "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getScriptDocValues.java:121)", "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValueScriptDocValues.java:115)", "ifdoc['cpinfo_youkewang.defprice'].value>0) {", " ^---- HERE" ], "script": "ifdoc['cpinfo_youkewang.defprice'].value>0) {return 1.0/doc['cpinfo_youkewang.defprice'].value;} else return 0;", "lang": "painless" }], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [{ "shard": 0, "index": "aiso_20q2v1_detail_gasstation", "node": "NE8IhhppQKalVXnjU-axBQ", "reason": { "type": "script_exception", "reason": "runtime error", "script_stack": [ "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getScriptDocValues.java:121)", "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValueScriptDocValues.java:115)", "ifdoc['cpinfo_youkewang.defprice'].value>0) {", " ^---- HERE" ], "script": "ifdoc['cpinfo_youkewang.defprice'].value>0) {return 1.0/doc['cpinfo_youkewang.defprice'].value;} else return 0;", "lang": "painless", "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 }
辗转之后偶然看了下报错信息,发现报错原因里面有提示如何看是否为空值,
于是把代码改成以下就可以了:
"rescore": [{ "window_size": 10000, "query": { "score_mode": "total", "rescore_query": { "function_score": { "script_score": { "script": "ifdoc['cpinfo_youkewang.defprice'].size) > 0 && doc['cpinfo_youkewang.defprice'].value>0) {return 1.0/doc['cpinfo_youkewang.defprice'].value;} else return 0;" } } } } }],
就是用得提示中得doc[<field>].size)来判断的。