如何在Elasticsearch本机脚本

时间:2015-07-28 00:25:04

标签: plugins elasticsearch transform

我添加了一个本机脚本,在添加新文档时作为转换运行。我需要文档ID,但它不作为脚本参数的一部分传入。只有_source作为参数传入,而不是_id值。有没有办法让ElasticSearch传入_id?或某种方式阅读它...不知何故?

下面是一个人为的ElasticSearch本机脚本示例,它演示了我正在谈论的内容。 setNextVar()由ElasticSearch和" ctx"传入了对象。该值是一个只有一个对象的Map,即_source对象。

但默认情况下,Elastic Key不会传入_id键/值对。我希望有一个原因,可以在映射json中配置本机脚本,告诉它传入文档ID。

public class ExampleNativeScript extends AbstractExecutableScript {

    /**
     * Factory class that serves native script to ElasticSearch
     */
    public static class Factory extends AbstractComponent implements NativeScriptFactory {

        @Inject
        public Factory(Settings settings, String prefixSettings) {
            super(settings, prefixSettings);
        }

        @Override
        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
            return new ExampleNativeScript(params);
        }
    }

    private final Map<String, Object> variables;
    private Map ctx = null;
    private Map source = null;

    public ExampleNativeScript(Map<String, Object> params) {
        this.variables = params;
    }

    @Override
    public void setNextVar(String name, Object value) {
        variables.put(name, value);

        if (name.equals("ctx")) {
            ctx = (Map<String, LinkedHashMap>) value;
            source = (Map<String, LinkedHashMap>) ctx.get("_source");
        } else {
            //never gets here
            System.out.println("Unexpected variable");
        }
    }

    @Override
    public Object run() {
        //PROBLEM: ctx only has _source.   _id does not get passed in so this blows chunks
        String documentId = ctx.get("_id").toString();
        System.out.println(documentId);
        return ctx;
    }
}

1 个答案:

答案 0 :(得分:0)

所以只是在ElasticSearch源代码中进行了一些挖掘,发现它的硬编码仅传递_source字段,而没有传递其他ctx级别字段。所以没有办法让/ config ElasticSearch传入_id

以下是调用本机脚本的DocumentMapper.transformSourceAsMap()setNextVar()函数的run()函数。它表明在ctx映射中唯一放置的是_source字段。

public Map<String, Object> transformSourceAsMap(Map<String, Object> sourceAsMap) {
    try {
        // We use the ctx variable and the _source name to be consistent with the update api.
        ExecutableScript executable = scriptService.executable(language, script, scriptType, ScriptContext.Standard.MAPPING, parameters);
        Map<String, Object> ctx = new HashMap<>(1);
        ctx.put("_source", sourceAsMap);
        executable.setNextVar("ctx", ctx);
        executable.run();
        ctx = (Map<String, Object>) executable.unwrap(ctx);
        return (Map<String, Object>) ctx.get("_source");
    } catch (Exception e) {
        throw new ElasticsearchIllegalArgumentException("failed to execute script", e);
    }
}