elasticsearch,scripting,Groovy,elasticsearch,Scripting" /> elasticsearch,scripting,Groovy,elasticsearch,Scripting" />

ElasticSearch:禁用Groovy的_分数字段上的聚合

ElasticSearch:禁用Groovy的_分数字段上的聚合,groovy,elasticsearch,scripting,Groovy,elasticsearch,Scripting,我看到的每个在_score字段上进行聚合或与之相关的示例(例如)似乎都需要使用脚本。由于安全原因,默认情况下ElasticSearch禁用动态脚本,有没有办法在不向每个ES节点加载脚本文件或重新启用动态脚本的情况下实现这一点 我最初的聚合如下所示: "aggs": { "terms_agg": { "terms": { "field": "field1", "order": {"max_score": "desc"}

我看到的每个在_score字段上进行聚合或与之相关的示例(例如)似乎都需要使用脚本。由于安全原因,默认情况下ElasticSearch禁用动态脚本,有没有办法在不向每个ES节点加载脚本文件或重新启用动态脚本的情况下实现这一点

我最初的聚合如下所示:

"aggs": {
    "terms_agg": {
        "terms": {
            "field": "field1",
            "order": {"max_score": "desc"}
        },
     "aggs": {
         "max_score": {
             "max": {"script": "_score"}
         },
         "top_terms": {
             "top_hits": {"size": 1}
         }
      }
}
尝试将表达式指定为lang似乎不起作用,因为ES会抛出一个错误,说明分数只能在用于排序时访问。我想不出还有什么其他方法可以按照分数字段来排序我的桶。有人有什么想法吗


编辑:澄清一下,我的限制是不能修改服务器端。也就是说,作为ES安装或配置的一部分,我无法添加或编辑任何内容。

一种可能的方法是使用其他可用的脚本选项<除非启用动态脚本,否则似乎无法使用代码>mvel。而且,除非达到1.6版本,否则我认为不可能为
mvel
groovy
启用动态脚本

剩下的是默认启用的
native
mustache
(用于模板)。我不认为自定义脚本可以通过
mustache
来完成,如果可能的话,我没有找到一种方法,我们只能使用
原生的
(Java)脚本

以下是我对此的看法:

  • 创建
    NativeScriptFactory
    的实现:
  • 或者,构建一个简单的Maven项目来将所有这些联系在一起。pom.xml:
我上面的示例只是将
\u分数
作为脚本返回,当然,它可以在更高级的场景中使用


编辑:如果不允许您触摸实例,那么我认为您没有任何选择。

ElasticSearch至少在1.7.1版和可能更早的版本中还提供了Lucene的表达式脚本语言的使用,并且由于表达式在默认情况下是沙盒的,所以它可以以与Groovy大致相同的方式用于动态内联脚本。在我们的例子中,我们的生产ES集群刚刚从1.4.1升级到1.7.1,我们决定不再使用Groovy,因为它是非沙盒的,尽管我们仍然希望使用动态脚本,因为在我们继续微调应用程序及其搜索层时,它们提供了易于部署和灵活性

在我们的例子中,编写一个本地Java脚本来替代我们的动态Groovy函数分数可能也是一种可能性,但我们想看看在我们的动态内联脚本语言中使用表达式的可行性。在阅读了文档之后,我发现我们可以简单地将“lang”属性从
“groovy”
更改为
“expression”
在我们的内联
function\u score
脚本中,使用
script.inline:sandbox
属性设置在
../config/elasticsearch.yml
文件中–function score脚本在没有任何其他修改的情况下工作。因此,我们现在可以继续在ElasticSearch中使用动态内联脚本,并在启用沙盒的情况下使用动态内联脚本(因为默认情况下表达式是沙盒的)。显然,还应实施其他安全措施,如在应用程序代理和防火墙后运行ES群集,以确保外部用户无法直接访问ES节点或ES API。然而,这是一个非常简单的更改,目前已经解决了Groovy缺少沙箱的问题,以及使它能够在没有沙箱的情况下运行的问题

虽然将动态脚本切换到表达式可能只在某些情况下有效或适用(取决于内联动态脚本的复杂性),但似乎值得分享这些信息,希望它能帮助其他开发人员

请注意,作为其他受支持的ES脚本语言之一,Mustach似乎仅可用于在搜索查询中创建模板。它似乎不适用于任何更复杂的脚本需求,如
功能评分
,尽管我不确定这在第一次通读更新的ES文档时是否完全清楚

最后,需要注意的另一个问题是,Lucene表达式脚本的使用在最新的ES版本中被标记为实验性功能,并且文档指出,由于此脚本扩展目前正在进行大量的开发工作,其使用或功能可能会在更高版本的ES中发生变化。因此,如果您切换到对任何脚本(动态或其他)使用Expression,则应在您的文档/开发人员说明中注明,以便在下次升级ES安装之前重新查看这些更改,以确保脚本保持兼容并按预期工作

至少在我们的情况下,除非我们愿意在最新版本的ES中再次启用非沙盒动态脚本(通过
script.inline:on
选项),以便内联Groovy脚本可以继续运行,否则切换到Lucene表达式脚本似乎是目前最好的选择

在未来的版本中,可以看到ES的脚本选择发生了什么变化,特别是考虑到Groovy的(显然无效的)沙箱选项将在2.0版中完全删除,这将是一件有趣的事情。希望能有其他保护措施来支持动态Groovy的使用,或者Lucene表达式脚本将取代Groovy,并支持开发人员已经在使用的所有类型的动态脚本

有关Lucene表达式的更多说明,请参见此处的ES文档:–本页也是有关计划从ES中删除Groovy沙箱选项的说明的来源
package com.foo.script;

import java.util.Map;

import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;

public class MyScriptNativeScriptFactory implements NativeScriptFactory {

    @Override
    public ExecutableScript newScript(Map<String, Object> arg0) {
        return new MyScript();
    }

}
package com.foo.script;

import java.io.IOException;

import org.elasticsearch.script.AbstractFloatSearchScript;

public class MyScript extends AbstractFloatSearchScript {

    @Override
    public float runAsFloat() {
        try {
            return score();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

}
<properties>
    <elasticsearch.version>1.5.2</elasticsearch.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>${elasticsearch.version}</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

<build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
{
  "aggs": {
    "max_score": {
      "max": {
        "script": "my_script",
        "lang": "native"
      }
    }
  }
}