Elasticsearch Painless中「Number」是否属于受限保留关键字?
问题:Elasticsearch 6.8 Painless脚本使用
Number作为变量名编译报错 我使用Elasticsearch Painless脚本已有两年时间,近期在6.8版本的Elasticsearch中遇到异常问题:当在Painless脚本中使用首字母大写的「Number」作为变量名时会触发编译报错,全小写的「number」以及「Numb」、「Numbe」等变量名变体均可正常使用。
复现场景
复现请求如下:
curl -X POST "http://localhost:9201/logs-my_app-default/_search?size=2&pretty" -H 'Content-Type: application/json' -d '{"_source": ["-1"], "script_fields": {"SCRIPT_FLAG": {"script": {"lang": "painless", "source": " def Number = 0; "}}}}'
问题出在代码行:def Number = 0;
抛出的错误信息如下:
"error" : { "root_cause" : [ { "type" : "script_exception", "reason" : "compile error", "script_stack" : [ " def Number = 0; ", " ^---- HERE" ], "script" : " def Number = 0; ", "lang" : "painless" } ], "type" : "search_phase_execution_exception", "reason" : "all shards failed", "phase" : "query", "grouped" : true, "failed_shards" : [ { "shard" : 0, "index" : "logs-my_app-default", "node" : "9jBNNKjdSIO6I8UH_HLVRw", "reason" : { "type" : "script_exception", "reason" : "compile error", "script_stack" : [ " def Number = 0; ", " ^---- HERE" ], "script" : " def Number = 0; ", "lang" : "painless", "caused_by" : { "type" : "illegal_argument_exception", "reason" : "invalid sequence of tokens near ['Number'].", "caused_by" : { "type" : "no_viable_alt_exception", "reason" : null } } } } ] }, "status" : 500 }
该问题在6.8版本Elasticsearch的任意索引上均会触发,本次复现使用的索引创建语句如下:
curl -X POST "localhost:9201/logs-my_app-default/_doc?pretty" -H 'Content-Type: application/json' -d' { "@timestamp": "2099-05-06T16:21:15.000Z", "event": { "original": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736" } } '
对应索引的mapping配置查询语句和返回结果如下:
curl -X GET "localhost:9201/logs-my_app-default/_mapping?pretty"
{ "logs-my_app-default" : { "mappings" : { "_doc" : { "properties" : { "@timestamp" : { "type" : "date" }, "event" : { "properties" : { "original" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } } } } } }
触发原因
Number是Painless脚本的大小写敏感内置类名,属于保留标识符,不允许直接作为变量名使用,因此会触发编译错误。其余变体比如全小写的number、截断的Numb/Numbe都不属于保留标识符,因此可以正常使用。
所有和Painless内置关键字、内置类名重名的变量名,都会触发同类编译错误。
适配解决方案
推荐最佳实践:当需要定义的Painless变量名与内置关键字/类名重名时,为变量添加下划线前缀规避冲突,示例如下:
def _Number = 0; // 替代 def Number = 0 def _Void = 0; // 替代 def Void = 0 def _System = 0; // 替代 def System = 0
也可根据业务含义调整变量命名,只要不与内置保留标识符完全一致即可。
内容的提问来源于stack exchange,提问作者Nikola Nikolovski
相关产品推荐
相关产品推荐

