原英文版地址: https://www.elastic.co/guide/en/elasticsearch/reference/7.7/modules-scripting-engine.html, 原文档版权归 www.elastic.co 所有
本地英文版地址: ../en/modules-scripting-engine.html
本地英文版地址: ../en/modules-scripting-engine.html
重要: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 当前版本文档。
ScriptEngine
是实现脚本语言的后端。
它还可以用来编写需要使用高级脚本内部机制的脚本。
例如,一个脚本希望在评分时使用词项的频率。
插件文档中有更多关于如何编写插件的信息,这样Elasticsearch就可以正确地加载它。
要注册ScriptEngine
,插件应该实现ScriptPlugin
接口并重写getScriptEngine(Settings settings)
方法。
下面是一个使用语言名称为expert_scripts
的自定义脚本引擎的示例。
它实现了一个名为pure_df
的脚本,该脚本可以用作搜索脚本来覆盖每个文档的分数,作为所提供词项的文档频率。
private static class MyExpertScriptEngine implements ScriptEngine { @Override public String getType() { return "expert_scripts"; } @Override public <T> T compile( String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> params ) { if (context.equals(ScoreScript.CONTEXT) == false) { throw new IllegalArgumentException(getType() + " scripts cannot be used for context [" + context.name + "]"); } // we use the script "source" as the script identifier if ("pure_df".equals(scriptSource)) { ScoreScript.Factory factory = new PureDfFactory(); return context.factoryClazz.cast(factory); } throw new IllegalArgumentException("Unknown script name " + scriptSource); } @Override public void close() { // optionally close resources } @Override public Set<ScriptContext<?>> getSupportedContexts() { return Collections.singleton(ScoreScript.CONTEXT); } private static class PureDfFactory implements ScoreScript.Factory, ScriptFactory { @Override public boolean isResultDeterministic() { // PureDfLeafFactory only uses deterministic APIs, this // implies the results are cacheable. return true; } @Override public LeafFactory newFactory( Map<String, Object> params, SearchLookup lookup ) { return new PureDfLeafFactory(params, lookup); } } private static class PureDfLeafFactory implements LeafFactory { private final Map<String, Object> params; private final SearchLookup lookup; private final String field; private final String term; private PureDfLeafFactory( Map<String, Object> params, SearchLookup lookup) { if (params.containsKey("field") == false) { throw new IllegalArgumentException( "Missing parameter [field]"); } if (params.containsKey("term") == false) { throw new IllegalArgumentException( "Missing parameter [term]"); } this.params = params; this.lookup = lookup; field = params.get("field").toString(); term = params.get("term").toString(); } @Override public boolean needs_score() { return false; // Return true if the script needs the score } @Override public ScoreScript newInstance(LeafReaderContext context) throws IOException { PostingsEnum postings = context.reader().postings( new Term(field, term)); if (postings == null) { /* * the field and/or term don't exist in this segment, * so always return 0 */ return new ScoreScript(params, lookup, context) { @Override public double execute( ExplanationHolder explanation ) { return 0.0d; } }; } return new ScoreScript(params, lookup, context) { int currentDocid = -1; @Override public void setDocument(int docid) { /* * advance has undefined behavior calling with * a docid <= its current docid */ if (postings.docID() < docid) { try { postings.advance(docid); } catch (IOException e) { throw new UncheckedIOException(e); } } currentDocid = docid; } @Override public double execute(ExplanationHolder explanation) { if (postings.docID() != currentDocid) { /* * advance moved past the current doc, so this * doc has no occurrences of the term */ return 0.0d; } try { return postings.freq(); } catch (IOException e) { throw new UncheckedIOException(e); } } }; } } }
可以通过将脚本的lang
指定为expert_scripts
,并将脚本的名称指定为脚本源来执行脚本:
POST /_search { "query": { "function_score": { "query": { "match": { "body": "foo" } }, "functions": [ { "script_score": { "script": { "source": "pure_df", "lang" : "expert_scripts", "params": { "field": "body", "term": "foo" } } } } ] } } }