为什么 Painless 编译器会抱怨 `new` 关键字?

Why Painless compiler complains about `new` keyword?

我正在尝试从 Painless 脚本中的字节创建字符串,如下所示,但最终在 new 关键字周围出现错误。我们的 Elasticsearch 是 6.2.8.

(最后的长度检查只是为了简洁,所以脚本 returns 布尔值。)

{
    "size": 1,
    "query": {
        "bool" : {
            "filter" : {
                "script" : {
                    "script" : {
                        "source": "byte[] a = new byte[]{65, 66, 67}; String b = new String(a, StandardCharsets.UTF_8); b.length() > 0",
                        "lang": "painless"
                     }
                }
            }
        }
    }
}

错误如下:

"script_stack": [
    "... {65, 66, 67}; String b = new String(a, StandardCha ...",
    "                             ^---- HERE"
],
"lang": "painless",
"type": "illegal_argument_exception",
"reason": "Unknown new call on type [java.lang.String]."

我不得不承认我很困惑。这是我第一次使用 Painless,但我看到了很多带有 new 关键字的例子。文档明确指出这是方法。呃,它甚至在上面的同一个脚本中。我错过了什么?为什么可以创建数组但不能创建字符串?

Post 通过聊天进行讨论,在进一步挖掘之后,我发现 String 不会像 link 中指定的那样通过 painless 公开构造函数。

link 将帮助您了解 ES painless 当前支持的所有 classes 或包。

出现错误是因为 StandardCharsets.UTF_8 属于包 import java.nio.charset.StandardCharsets; 并且从上面 link 看来目前不支持或提及此 class早些时候 link 共享。

此外,我认为 painless 不允许您使用 import 语句。但是,您可以尝试的是 link 中提到的,其中说明如下:

As of 6.2, painless can now have it's whitelist extended by plugins. Unfortunately this is not well documented yet, but we do have an example plugin.

The basic idea is to create a plugin that "extends" painless, and tells painless about additional whitelist elements through SPI. The whitelist is per script context, so you will need to add these elements for any types of scripts you use. There is no central list of script contexts, but it looks like in this case you are using an update script? So that would be the update context. In your script, you can then use the classes, no importing necessary.

如果您打算编写自己的插件,您可能需要查看第 for plugin authors in the Introduction to plugins 页面。