From 760acb3de773275f141b34109b9ca5c72ea58800 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 28 Sep 2018 16:21:05 -0700 Subject: [PATCH 01/11] Scripting: Convert script fields to use script context This commit removes the use of SearchScript for script fields and adds a new FieldScript. --- .../painless-field-context.asciidoc | 7 +- .../index/query/InnerHitContextBuilder.java | 8 +- .../org/elasticsearch/script/FieldScript.java | 100 ++++++++++++++++++ .../elasticsearch/script/ScriptModule.java | 1 + .../elasticsearch/search/SearchService.java | 6 +- .../metrics/TopHitsAggregationBuilder.java | 6 +- .../fetch/subphase/ScriptFieldsContext.java | 8 +- .../subphase/ScriptFieldsFetchSubPhase.java | 12 +-- .../script/ScriptServiceTests.java | 24 ++--- .../script/MockScriptEngine.java | 17 +++ 10 files changed, 152 insertions(+), 37 deletions(-) create mode 100644 server/src/main/java/org/elasticsearch/script/FieldScript.java diff --git a/docs/painless/painless-contexts/painless-field-context.asciidoc b/docs/painless/painless-contexts/painless-field-context.asciidoc index 4c767ca389115..063f9a55d20f2 100644 --- a/docs/painless/painless-contexts/painless-field-context.asciidoc +++ b/docs/painless/painless-contexts/painless-field-context.asciidoc @@ -14,13 +14,10 @@ a customized value for each document in the results of a query. Contains the fields of the specified document where each field is a `List` of values. -{ref}/mapping-source-field.html[`ctx['_source']`] (`Map`):: +{ref}/mapping-source-field.html[`params['_source']`] (`Map`):: Contains extracted JSON in a `Map` and `List` structure for the fields existing in a stored document. -`_score` (`double` read-only):: - The original score of the specified document. - *Return* `Object`:: @@ -28,4 +25,4 @@ a customized value for each document in the results of a query. *API* -The standard <> is available. \ No newline at end of file +The standard <> is available. diff --git a/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java b/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java index 58d271bb8206c..1fe781f38ce27 100644 --- a/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java @@ -20,7 +20,7 @@ package org.elasticsearch.index.query; import org.elasticsearch.index.IndexSettings; -import org.elasticsearch.script.SearchScript; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.DocValueFieldsContext; import org.elasticsearch.search.fetch.subphase.InnerHitsContext; @@ -88,10 +88,10 @@ protected void setupInnerHitsContext(QueryShardContext queryShardContext, if (innerHitBuilder.getScriptFields() != null) { for (SearchSourceBuilder.ScriptField field : innerHitBuilder.getScriptFields()) { QueryShardContext innerContext = innerHitsContext.getQueryShardContext(); - SearchScript.Factory factory = innerContext.getScriptService().compile(field.script(), SearchScript.CONTEXT); - SearchScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), innerHitsContext.lookup()); + FieldScript.Factory factory = innerContext.getScriptService().compile(field.script(), FieldScript.CONTEXT); + FieldScript.LeafFactory fieldScript = factory.newFactory(field.script().getParams(), innerHitsContext.lookup()); innerHitsContext.scriptFields().add(new org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField( - field.fieldName(), searchScript, field.ignoreFailure())); + field.fieldName(), fieldScript, field.ignoreFailure())); } } if (innerHitBuilder.getFetchSourceContext() != null) { diff --git a/server/src/main/java/org/elasticsearch/script/FieldScript.java b/server/src/main/java/org/elasticsearch/script/FieldScript.java new file mode 100644 index 0000000000000..09d3aeb0a21c8 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/script/FieldScript.java @@ -0,0 +1,100 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.script; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.search.lookup.LeafDocLookup; +import org.elasticsearch.search.lookup.LeafSearchLookup; +import org.elasticsearch.search.lookup.SearchLookup; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * A script to produce dynamic values for return fields. + */ +public abstract class FieldScript { + + private static final Map DEPRECATIONS; + + static { + Map deprecations = new HashMap<>(); + deprecations.put( + "doc", + "Accessing variable [doc] via [params.doc] from within a terms-set-query-script " + + "is deprecated in favor of directly accessing [doc]." + ); + deprecations.put( + "_doc", + "Accessing variable [doc] via [params._doc] from within a terms-set-query-script " + + "is deprecated in favor of directly accessing [doc]." + ); + DEPRECATIONS = Collections.unmodifiableMap(deprecations); + } + + /** The generic runtime parameters for the script. */ + private final Map params; + + /** A leaf lookup for the bound segment this script will operate on. */ + private final LeafSearchLookup leafLookup; + + public FieldScript(Map params, SearchLookup lookup, LeafReaderContext leafContext) { + this.leafLookup = lookup.getLeafSearchLookup(leafContext); + params = new HashMap<>(params); + params.putAll(leafLookup.asMap()); + this.params = new ParameterMap(params, DEPRECATIONS); + } + + public abstract Object execute(); + + /** The leaf lookup for the Lucene segment this script was created for. */ + protected final LeafSearchLookup getLeafLookup() { + return leafLookup; + } + + /** Return the parameters for this script. */ + public Map getParams() { + return params; + } + + /** The doc lookup for the Lucene segment this script was created for. */ + public final LeafDocLookup getDoc() { + return leafLookup.doc(); + } + + /** Set the current document to run the script on next. */ + public void setDocument(int docid) { + leafLookup.setDocument(docid); + } + + /** A factory to construct {@link SearchScript} instances. */ + public interface LeafFactory { + FieldScript newInstance(LeafReaderContext ctx) throws IOException; + } + + public interface Factory { + LeafFactory newFactory(Map params, SearchLookup lookup); + } + + /** The context used to compile {@link FieldScript} factories. */ + public static final ScriptContext CONTEXT = new ScriptContext<>("field", Factory.class); +} diff --git a/server/src/main/java/org/elasticsearch/script/ScriptModule.java b/server/src/main/java/org/elasticsearch/script/ScriptModule.java index 968bc143ba83a..da52b2b833752 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptModule.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptModule.java @@ -40,6 +40,7 @@ public class ScriptModule { public static final Map> CORE_CONTEXTS; static { CORE_CONTEXTS = Stream.of( + FieldScript.CONTEXT, SearchScript.CONTEXT, SearchScript.AGGS_CONTEXT, ScoreScript.CONTEXT, diff --git a/server/src/main/java/org/elasticsearch/search/SearchService.java b/server/src/main/java/org/elasticsearch/search/SearchService.java index d8829bd11d386..6512e25fc0b78 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchService.java +++ b/server/src/main/java/org/elasticsearch/search/SearchService.java @@ -58,8 +58,8 @@ import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason; import org.elasticsearch.node.ResponseCollectorService; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.script.ScriptService; -import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.aggregations.AggregationInitializationException; import org.elasticsearch.search.aggregations.AggregatorFactories; import org.elasticsearch.search.aggregations.InternalAggregation; @@ -863,8 +863,8 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc + IndexSettings.MAX_SCRIPT_FIELDS_SETTING.getKey() + "] index level setting."); } for (org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField field : source.scriptFields()) { - SearchScript.Factory factory = scriptService.compile(field.script(), SearchScript.CONTEXT); - SearchScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), context.lookup()); + FieldScript.Factory factory = scriptService.compile(field.script(), FieldScript.CONTEXT); + FieldScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), context.lookup()); context.scriptFields().add(new ScriptField(field.fieldName(), searchScript, field.ignoreFailure())); } } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java index c2add245058b2..debbacdc6196c 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java @@ -28,8 +28,8 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.script.Script; -import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationInitializationException; @@ -566,8 +566,8 @@ protected TopHitsAggregatorFactory doBuild(SearchContext context, AggregatorFact if (scriptFields != null) { for (ScriptField field : scriptFields) { QueryShardContext shardContext = context.getQueryShardContext(); - SearchScript.Factory factory = shardContext.getScriptService().compile(field.script(), SearchScript.CONTEXT); - SearchScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), shardContext.lookup()); + FieldScript.Factory factory = shardContext.getScriptService().compile(field.script(), FieldScript.CONTEXT); + FieldScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), shardContext.lookup()); fields.add(new org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField( field.fieldName(), searchScript, field.ignoreFailure())); } diff --git a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsContext.java b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsContext.java index 9e43b0bdd32b4..4c1bd4aacb5cc 100644 --- a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsContext.java +++ b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsContext.java @@ -19,7 +19,7 @@ package org.elasticsearch.search.fetch.subphase; -import org.elasticsearch.script.SearchScript; +import org.elasticsearch.script.FieldScript; import java.util.ArrayList; import java.util.List; @@ -28,10 +28,10 @@ public class ScriptFieldsContext { public static class ScriptField { private final String name; - private final SearchScript.LeafFactory script; + private final FieldScript.LeafFactory script; private final boolean ignoreException; - public ScriptField(String name, SearchScript.LeafFactory script, boolean ignoreException) { + public ScriptField(String name, FieldScript.LeafFactory script, boolean ignoreException) { this.name = name; this.script = script; this.ignoreException = ignoreException; @@ -41,7 +41,7 @@ public String name() { return name; } - public SearchScript.LeafFactory script() { + public FieldScript.LeafFactory script() { return this.script; } diff --git a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsFetchSubPhase.java b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsFetchSubPhase.java index 022a97b3f8dfc..532441c0cf934 100644 --- a/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsFetchSubPhase.java +++ b/server/src/main/java/org/elasticsearch/search/fetch/subphase/ScriptFieldsFetchSubPhase.java @@ -23,7 +23,7 @@ import org.apache.lucene.index.ReaderUtil; import org.elasticsearch.common.document.DocumentField; import org.elasticsearch.common.util.CollectionUtils; -import org.elasticsearch.script.SearchScript; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.internal.SearchContext; @@ -49,7 +49,7 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId)); int lastReaderId = -1; - SearchScript[] leafScripts = null; + FieldScript[] leafScripts = null; List scriptFields = context.scriptFields().fields(); final IndexReader reader = context.searcher().getIndexReader(); for (SearchHit hit : hits) { @@ -64,7 +64,7 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept leafScripts[i].setDocument(docId); final Object value; try { - value = leafScripts[i].run(); + value = leafScripts[i].execute(); CollectionUtils.ensureNoSelfReferences(value, "ScriptFieldsFetchSubPhase leaf script " + i); } catch (RuntimeException e) { if (scriptFields.get(i).ignoreException()) { @@ -91,9 +91,9 @@ public void hitsExecute(SearchContext context, SearchHit[] hits) throws IOExcept } } - private SearchScript[] createLeafScripts(LeafReaderContext context, - List scriptFields) { - SearchScript[] scripts = new SearchScript[scriptFields.size()]; + private FieldScript[] createLeafScripts(LeafReaderContext context, + List scriptFields) { + FieldScript[] scripts = new FieldScript[scriptFields.size()]; for (int i = 0; i < scripts.length; i++) { try { scripts[i] = scriptFields.get(i).script().newInstance(context); diff --git a/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index fcb868c0e0e84..745abab77651c 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -150,22 +150,22 @@ public void testNotSupportedDisableDynamicSetting() throws IOException { public void testInlineScriptCompiledOnceCache() throws IOException { buildScriptService(Settings.EMPTY); Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap()); - SearchScript.Factory factoryScript1 = scriptService.compile(script, SearchScript.CONTEXT); - SearchScript.Factory factoryScript2 = scriptService.compile(script, SearchScript.CONTEXT); + FieldScript.Factory factoryScript1 = scriptService.compile(script, FieldScript.CONTEXT); + FieldScript.Factory factoryScript2 = scriptService.compile(script, FieldScript.CONTEXT); assertThat(factoryScript1, sameInstance(factoryScript2)); } public void testAllowAllScriptTypeSettings() throws IOException { buildScriptService(Settings.EMPTY); - assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); - assertCompileAccepted(null, "script", ScriptType.STORED, SearchScript.CONTEXT); + assertCompileAccepted("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); + assertCompileAccepted(null, "script", ScriptType.STORED, FieldScript.CONTEXT); } public void testAllowAllScriptContextSettings() throws IOException { buildScriptService(Settings.EMPTY); - assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); + assertCompileAccepted("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.AGGS_CONTEXT); assertCompileAccepted("painless", "script", ScriptType.INLINE, UpdateScript.CONTEXT); assertCompileAccepted("painless", "script", ScriptType.INLINE, IngestScript.CONTEXT); @@ -176,16 +176,16 @@ public void testAllowSomeScriptTypeSettings() throws IOException { builder.put("script.allowed_types", "inline"); buildScriptService(builder.build()); - assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); - assertCompileRejected(null, "script", ScriptType.STORED, SearchScript.CONTEXT); + assertCompileAccepted("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); + assertCompileRejected(null, "script", ScriptType.STORED, FieldScript.CONTEXT); } public void testAllowSomeScriptContextSettings() throws IOException { Settings.Builder builder = Settings.builder(); - builder.put("script.allowed_contexts", "search, aggs"); + builder.put("script.allowed_contexts", "search, field, aggs"); buildScriptService(builder.build()); - assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); + assertCompileAccepted("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); assertCompileAccepted("painless", "script", ScriptType.INLINE, SearchScript.AGGS_CONTEXT); assertCompileRejected("painless", "script", ScriptType.INLINE, UpdateScript.CONTEXT); } @@ -195,8 +195,8 @@ public void testAllowNoScriptTypeSettings() throws IOException { builder.put("script.allowed_types", "none"); buildScriptService(builder.build()); - assertCompileRejected("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); - assertCompileRejected(null, "script", ScriptType.STORED, SearchScript.CONTEXT); + assertCompileRejected("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); + assertCompileRejected(null, "script", ScriptType.STORED, FieldScript.CONTEXT); } public void testAllowNoScriptContextSettings() throws IOException { @@ -204,7 +204,7 @@ public void testAllowNoScriptContextSettings() throws IOException { builder.put("script.allowed_contexts", "none"); buildScriptService(builder.build()); - assertCompileRejected("painless", "script", ScriptType.INLINE, SearchScript.CONTEXT); + assertCompileRejected("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); assertCompileRejected("painless", "script", ScriptType.INLINE, SearchScript.AGGS_CONTEXT); } diff --git a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java index e81c9f95ba2f6..edc5e24baf79d 100644 --- a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java +++ b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java @@ -93,6 +93,17 @@ public T compile(String name, String source, ScriptContext context, Map + ctx -> new FieldScript(parameters, lookup, ctx) { + @Override + public Object execute() { + Map vars = createVars(parameters); + vars.putAll(getLeafLookup().asMap()); + return script.apply(vars); + } + }; + return context.factoryClazz.cast(factory); } else if(context.instanceClazz.equals(TermsSetQueryScript.class)) { TermsSetQueryScript.Factory factory = (parameters, lookup) -> (TermsSetQueryScript.LeafFactory) ctx -> new TermsSetQueryScript(parameters, lookup, ctx) { @@ -213,6 +224,12 @@ public String execute() { throw new IllegalArgumentException("mock script engine does not know how to handle context [" + context.name + "]"); } + private Map createVars(Map params) { + Map vars = new HashMap<>(); + vars.put("params", params); + return vars; + } + public class MockCompiledScript { private final String name; From bf50ea5905b764228e4828de6429baed7d88612b Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 28 Sep 2018 17:44:07 -0700 Subject: [PATCH 02/11] address PR comments --- .../painless-contexts/painless-field-context.asciidoc | 2 +- .../java/org/elasticsearch/script/FieldScript.java | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/painless/painless-contexts/painless-field-context.asciidoc b/docs/painless/painless-contexts/painless-field-context.asciidoc index 063f9a55d20f2..80307b25ea545 100644 --- a/docs/painless/painless-contexts/painless-field-context.asciidoc +++ b/docs/painless/painless-contexts/painless-field-context.asciidoc @@ -14,7 +14,7 @@ a customized value for each document in the results of a query. Contains the fields of the specified document where each field is a `List` of values. -{ref}/mapping-source-field.html[`params['_source']`] (`Map`):: +{ref}/mapping-source-field.html[`params['_source']`] (`Map`, read-only):: Contains extracted JSON in a `Map` and `List` structure for the fields existing in a stored document. diff --git a/server/src/main/java/org/elasticsearch/script/FieldScript.java b/server/src/main/java/org/elasticsearch/script/FieldScript.java index 09d3aeb0a21c8..22e76c2109afb 100644 --- a/server/src/main/java/org/elasticsearch/script/FieldScript.java +++ b/server/src/main/java/org/elasticsearch/script/FieldScript.java @@ -20,7 +20,7 @@ package org.elasticsearch.script; import org.apache.lucene.index.LeafReaderContext; -import org.elasticsearch.search.lookup.LeafDocLookup; +import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.search.lookup.LeafSearchLookup; import org.elasticsearch.search.lookup.SearchLookup; @@ -34,18 +34,20 @@ */ public abstract class FieldScript { + public static final String[] PARAMETERS = {}; + private static final Map DEPRECATIONS; static { Map deprecations = new HashMap<>(); deprecations.put( "doc", - "Accessing variable [doc] via [params.doc] from within a terms-set-query-script " + + "Accessing variable [doc] via [params.doc] from within a field script " + "is deprecated in favor of directly accessing [doc]." ); deprecations.put( "_doc", - "Accessing variable [doc] via [params._doc] from within a terms-set-query-script " + + "Accessing variable [doc] via [params._doc] from within a field script " + "is deprecated in favor of directly accessing [doc]." ); DEPRECATIONS = Collections.unmodifiableMap(deprecations); @@ -77,7 +79,7 @@ public Map getParams() { } /** The doc lookup for the Lucene segment this script was created for. */ - public final LeafDocLookup getDoc() { + public final Map> getDoc() { return leafLookup.doc(); } From 1759944c35b6561a7dec03d0727c8cd642c65947 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 17 Oct 2018 12:18:39 -0700 Subject: [PATCH 03/11] add expression support to FieldScript --- .../expression/ExpressionFieldScript.java | 67 +++++++++++ .../expression/ExpressionScriptEngine.java | 21 ++++ .../ExpressionFieldScriptTests.java | 105 ++++++++++++++++++ .../org/elasticsearch/script/FieldScript.java | 6 + 4 files changed, 199 insertions(+) create mode 100644 modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionFieldScript.java create mode 100644 modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionFieldScriptTests.java diff --git a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionFieldScript.java b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionFieldScript.java new file mode 100644 index 0000000000000..14fd1dd6c1242 --- /dev/null +++ b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionFieldScript.java @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.script.expression; + +import org.apache.lucene.expressions.Expression; +import org.apache.lucene.expressions.SimpleBindings; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.search.DoubleValues; +import org.apache.lucene.search.DoubleValuesSource; +import org.elasticsearch.script.FieldScript; +import org.elasticsearch.script.GeneralScriptException; + +import java.io.IOException; + +public class ExpressionFieldScript implements FieldScript.LeafFactory { + private final Expression exprScript; + private final DoubleValuesSource source; + + ExpressionFieldScript(Expression e, SimpleBindings b) { + this.exprScript = e; + this.source = exprScript.getDoubleValuesSource(b); + } + + @Override + public FieldScript newInstance(final LeafReaderContext leaf) throws IOException { + return new FieldScript() { + + // Fake the scorer until setScorer is called. + DoubleValues values = source.getValues(leaf, null); + + @Override + public Object execute() { + try { + return values.doubleValue(); + } catch (Exception exception) { + throw new GeneralScriptException("Error evaluating " + exprScript, exception); + } + } + + @Override + public void setDocument(int d) { + try { + values.advanceExact(d); + } catch (IOException e) { + throw new IllegalStateException("Can't advance to doc using " + exprScript, e); + } + } + }; + } +} diff --git a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java index 5d47c87a445a2..94a3d32465127 100644 --- a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java +++ b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java @@ -41,6 +41,7 @@ import org.elasticsearch.script.BucketAggregationScript; import org.elasticsearch.script.BucketAggregationSelectorScript; import org.elasticsearch.script.ClassPermission; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.script.FilterScript; import org.elasticsearch.script.NumberSortScript; import org.elasticsearch.script.ScoreScript; @@ -139,6 +140,9 @@ public boolean execute() { } else if (context.instanceClazz.equals(NumberSortScript.class)) { NumberSortScript.Factory factory = (p, lookup) -> newSortScript(expr, lookup, p); return context.factoryClazz.cast(factory); + } else if (context.instanceClazz.equals(FieldScript.class)) { + FieldScript.Factory factory = (p, lookup) -> newFieldScript(expr, lookup, p); + return context.factoryClazz.cast(factory); } throw new IllegalArgumentException("expression engine does not know how to handle script context [" + context.name + "]"); } @@ -289,6 +293,23 @@ private AggregationScript.LeafFactory newAggregationScript(Expression expr, Sear return new ExpressionAggregationScript(expr, bindings, specialValue); } + private FieldScript.LeafFactory newFieldScript(Expression expr, SearchLookup lookup, @Nullable Map vars) { + SimpleBindings bindings = new SimpleBindings(); + for (String variable : expr.variables) { + try { + if (vars != null && vars.containsKey(variable)) { + bindFromParams(vars, bindings, variable); + } else { + final ValueSource valueSource = getDocValueSource(variable, lookup); + bindings.add(variable, valueSource.asDoubleValuesSource()); + } + } catch (Exception e) { + throw convertToScriptException("link error", expr.sourceText, variable, e); + } + } + return new ExpressionFieldScript(expr, bindings); + } + /** * This is a hack for filter scripts, which must return booleans instead of doubles as expression do. * See https://github.com/elastic/elasticsearch/issues/26429. diff --git a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionFieldScriptTests.java b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionFieldScriptTests.java new file mode 100644 index 0000000000000..b1872b30f1f17 --- /dev/null +++ b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionFieldScriptTests.java @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.script.expression; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.fielddata.AtomicNumericFieldData; +import org.elasticsearch.index.fielddata.IndexNumericFieldData; +import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.NumberFieldMapper; +import org.elasticsearch.script.FieldScript; +import org.elasticsearch.script.ScriptException; +import org.elasticsearch.search.lookup.SearchLookup; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.text.ParseException; +import java.util.Collections; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ExpressionFieldScriptTests extends ESTestCase { + private ExpressionScriptEngine service; + private SearchLookup lookup; + + @Override + public void setUp() throws Exception { + super.setUp(); + + NumberFieldMapper.NumberFieldType fieldType = new NumberFieldMapper.NumberFieldType(NumberFieldMapper.NumberType.DOUBLE); + MapperService mapperService = mock(MapperService.class); + when(mapperService.fullName("field")).thenReturn(fieldType); + when(mapperService.fullName("alias")).thenReturn(fieldType); + + SortedNumericDoubleValues doubleValues = mock(SortedNumericDoubleValues.class); + when(doubleValues.advanceExact(anyInt())).thenReturn(true); + when(doubleValues.nextValue()).thenReturn(2.718); + + AtomicNumericFieldData atomicFieldData = mock(AtomicNumericFieldData.class); + when(atomicFieldData.getDoubleValues()).thenReturn(doubleValues); + + IndexNumericFieldData fieldData = mock(IndexNumericFieldData.class); + when(fieldData.getFieldName()).thenReturn("field"); + when(fieldData.load(anyObject())).thenReturn(atomicFieldData); + + service = new ExpressionScriptEngine(Settings.EMPTY); + lookup = new SearchLookup(mapperService, ignored -> fieldData, null); + } + + private FieldScript.LeafFactory compile(String expression) { + FieldScript.Factory factory = service.compile(null, expression, FieldScript.CONTEXT, Collections.emptyMap()); + return factory.newFactory(Collections.emptyMap(), lookup); + } + + public void testCompileError() { + ScriptException e = expectThrows(ScriptException.class, () -> { + compile("doc['field'].value * *@#)(@$*@#$ + 4"); + }); + assertTrue(e.getCause() instanceof ParseException); + } + + public void testLinkError() { + ScriptException e = expectThrows(ScriptException.class, () -> { + compile("doc['nonexistent'].value * 5"); + }); + assertTrue(e.getCause() instanceof ParseException); + } + + public void testFieldAccess() throws IOException { + FieldScript script = compile("doc['field'].value").newInstance(null); + script.setDocument(1); + + Object result = script.execute(); + assertThat(result, equalTo(2.718)); + } + + public void testFieldAccessWithFieldAlias() throws IOException { + FieldScript script = compile("doc['alias'].value").newInstance(null); + script.setDocument(1); + + Object result = script.execute(); + assertThat(result, equalTo(2.718)); + } +} diff --git a/server/src/main/java/org/elasticsearch/script/FieldScript.java b/server/src/main/java/org/elasticsearch/script/FieldScript.java index 22e76c2109afb..98649dbb33043 100644 --- a/server/src/main/java/org/elasticsearch/script/FieldScript.java +++ b/server/src/main/java/org/elasticsearch/script/FieldScript.java @@ -66,6 +66,12 @@ public FieldScript(Map params, SearchLookup lookup, LeafReaderCo this.params = new ParameterMap(params, DEPRECATIONS); } + // for expression engine + protected FieldScript() { + params = null; + leafLookup = null; + } + public abstract Object execute(); /** The leaf lookup for the Lucene segment this script was created for. */ From 433d149137d1bd4b23c264f08a5679d2ad841d15 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 17 Oct 2018 16:35:30 -0700 Subject: [PATCH 04/11] fix example --- .../painlesswhitelist/ExampleWhitelistExtension.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java index 9e3bc66e7d58d..ca35db5a81b3d 100644 --- a/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java +++ b/plugins/examples/painless-whitelist/src/main/java/org/elasticsearch/example/painlesswhitelist/ExampleWhitelistExtension.java @@ -19,15 +19,15 @@ package org.elasticsearch.example.painlesswhitelist; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import org.elasticsearch.painless.spi.PainlessExtension; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.spi.WhitelistLoader; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.script.ScriptContext; -import org.elasticsearch.script.SearchScript; + +import java.util.Collections; +import java.util.List; +import java.util.Map; /** An extension of painless which adds a whitelist. */ public class ExampleWhitelistExtension implements PainlessExtension { @@ -37,6 +37,6 @@ public class ExampleWhitelistExtension implements PainlessExtension { @Override public Map, List> getContextWhitelists() { - return Collections.singletonMap(SearchScript.CONTEXT, Collections.singletonList(WHITELIST)); + return Collections.singletonMap(FieldScript.CONTEXT, Collections.singletonList(WHITELIST)); } } From 71db8be67f461de5e954d2630fd4ddaa0df6812c Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 17 Oct 2018 16:37:20 -0700 Subject: [PATCH 05/11] fix sql use of field script --- .../main/java/org/elasticsearch/script/ScriptModule.java | 1 - .../xpack/sql/plugin/SqlPainlessExtension.java | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/script/ScriptModule.java b/server/src/main/java/org/elasticsearch/script/ScriptModule.java index c1075534e0cb5..1c53ef133de86 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptModule.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptModule.java @@ -41,7 +41,6 @@ public class ScriptModule { static { CORE_CONTEXTS = Stream.of( FieldScript.CONTEXT, - SearchScript.CONTEXT, AggregationScript.CONTEXT, ScoreScript.CONTEXT, NumberSortScript.CONTEXT, diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPainlessExtension.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPainlessExtension.java index f0ca0cb87308d..feacbabe5e29f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPainlessExtension.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPainlessExtension.java @@ -10,15 +10,15 @@ import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.AggregationScript; import org.elasticsearch.script.BucketAggregationSelectorScript; +import org.elasticsearch.script.FieldScript; import org.elasticsearch.script.FilterScript; +import org.elasticsearch.script.NumberSortScript; import org.elasticsearch.script.ScriptContext; -import org.elasticsearch.script.SearchScript; +import org.elasticsearch.script.StringSortScript; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.elasticsearch.script.NumberSortScript; -import org.elasticsearch.script.StringSortScript; import static java.util.Collections.singletonList; @@ -32,7 +32,7 @@ public Map, List> getContextWhitelists() { List list = singletonList(WHITELIST); whitelist.put(FilterScript.CONTEXT, list); whitelist.put(AggregationScript.CONTEXT, list); - whitelist.put(SearchScript.CONTEXT, list); + whitelist.put(FieldScript.CONTEXT, list); whitelist.put(NumberSortScript.CONTEXT, list); whitelist.put(StringSortScript.CONTEXT, list); whitelist.put(BucketAggregationSelectorScript.CONTEXT, list); From 5016bca3c7ca23514d129265c787cf1108e06ab1 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 17 Oct 2018 16:47:28 -0700 Subject: [PATCH 06/11] remove leftover search script context refs --- .../script/expression/ExpressionTests.java | 112 ------------------ .../painless/ScriptTestCase.java | 2 - .../test/painless/16_update2.yml | 4 +- 3 files changed, 2 insertions(+), 116 deletions(-) delete mode 100644 modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionTests.java diff --git a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionTests.java b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionTests.java deleted file mode 100644 index 33e6239002eb1..0000000000000 --- a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/ExpressionTests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.expression; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.fielddata.AtomicNumericFieldData; -import org.elasticsearch.index.fielddata.IndexNumericFieldData; -import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.NumberFieldMapper.NumberFieldType; -import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType; -import org.elasticsearch.script.ScriptException; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.lookup.SearchLookup; -import org.elasticsearch.test.ESTestCase; - -import java.io.IOException; -import java.text.ParseException; -import java.util.Collections; - -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ExpressionTests extends ESTestCase { - private ExpressionScriptEngine service; - private SearchLookup lookup; - - @Override - public void setUp() throws Exception { - super.setUp(); - - NumberFieldType fieldType = new NumberFieldType(NumberType.DOUBLE); - MapperService mapperService = mock(MapperService.class); - when(mapperService.fullName("field")).thenReturn(fieldType); - when(mapperService.fullName("alias")).thenReturn(fieldType); - - SortedNumericDoubleValues doubleValues = mock(SortedNumericDoubleValues.class); - when(doubleValues.advanceExact(anyInt())).thenReturn(true); - when(doubleValues.nextValue()).thenReturn(2.718); - - AtomicNumericFieldData atomicFieldData = mock(AtomicNumericFieldData.class); - when(atomicFieldData.getDoubleValues()).thenReturn(doubleValues); - - IndexNumericFieldData fieldData = mock(IndexNumericFieldData.class); - when(fieldData.getFieldName()).thenReturn("field"); - when(fieldData.load(anyObject())).thenReturn(atomicFieldData); - - service = new ExpressionScriptEngine(Settings.EMPTY); - lookup = new SearchLookup(mapperService, ignored -> fieldData, null); - } - - private SearchScript.LeafFactory compile(String expression) { - SearchScript.Factory factory = service.compile(null, expression, SearchScript.CONTEXT, Collections.emptyMap()); - return factory.newFactory(Collections.emptyMap(), lookup); - } - - public void testNeedsScores() { - assertFalse(compile("1.2").needs_score()); - assertFalse(compile("doc['field'].value").needs_score()); - assertTrue(compile("1/_score").needs_score()); - assertTrue(compile("doc['field'].value * _score").needs_score()); - } - - public void testCompileError() { - ScriptException e = expectThrows(ScriptException.class, () -> { - compile("doc['field'].value * *@#)(@$*@#$ + 4"); - }); - assertTrue(e.getCause() instanceof ParseException); - } - - public void testLinkError() { - ScriptException e = expectThrows(ScriptException.class, () -> { - compile("doc['nonexistent'].value * 5"); - }); - assertTrue(e.getCause() instanceof ParseException); - } - - public void testFieldAccess() throws IOException { - SearchScript script = compile("doc['field'].value").newInstance(null); - script.setDocument(1); - - double result = script.runAsDouble(); - assertEquals(2.718, result, 0.0); - } - - public void testFieldAccessWithFieldAlias() throws IOException { - SearchScript script = compile("doc['alias'].value").newInstance(null); - script.setDocument(1); - - double result = script.runAsDouble(); - assertEquals(2.718, result, 0.0); - } -} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index e69a1ad5dcfd0..5a4c5de015bc1 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -27,7 +27,6 @@ import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptException; -import org.elasticsearch.script.SearchScript; import org.elasticsearch.test.ESTestCase; import org.junit.Before; @@ -67,7 +66,6 @@ protected Settings scriptEngineSettings() { */ protected Map, List> scriptContexts() { Map, List> contexts = new HashMap<>(); - contexts.put(SearchScript.CONTEXT, Whitelist.BASE_WHITELISTS); contexts.put(PainlessTestScript.CONTEXT, Whitelist.BASE_WHITELISTS); return contexts; } diff --git a/modules/lang-painless/src/test/resources/rest-api-spec/test/painless/16_update2.yml b/modules/lang-painless/src/test/resources/rest-api-spec/test/painless/16_update2.yml index 253676bda8e38..999733ff14be7 100644 --- a/modules/lang-painless/src/test/resources/rest-api-spec/test/painless/16_update2.yml +++ b/modules/lang-painless/src/test/resources/rest-api-spec/test/painless/16_update2.yml @@ -38,12 +38,12 @@ catch: bad_request put_script: id: "1" - context: "search" + context: "score" body: { "script": {"lang": "painless", "source": "_score * foo bar + doc['myParent.weight'].value"} } - do: catch: /compile error/ put_script: id: "1" - context: "search" + context: "score" body: { "script": {"lang": "painless", "source": "_score * foo bar + doc['myParent.weight'].value"} } From 588a7cba19db94838ff909800af6b9c939aeacb9 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 17 Oct 2018 17:36:54 -0700 Subject: [PATCH 07/11] fix test --- .../test/java/org/elasticsearch/script/ScriptServiceTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index bafaefd8d0c48..22a250710ba3c 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -182,7 +182,7 @@ public void testAllowSomeScriptTypeSettings() throws IOException { public void testAllowSomeScriptContextSettings() throws IOException { Settings.Builder builder = Settings.builder(); - builder.put("script.allowed_contexts", "search, field, aggs"); + builder.put("script.allowed_contexts", "field, aggs"); buildScriptService(builder.build()); assertCompileAccepted("painless", "script", ScriptType.INLINE, FieldScript.CONTEXT); From 9e9c6d3b81a6f926759a429b02568af491cabf70 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Thu, 18 Oct 2018 00:12:55 -0700 Subject: [PATCH 08/11] fix test use of params --- .../java/org/elasticsearch/search/fields/SearchFieldsIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/search/fields/SearchFieldsIT.java b/server/src/test/java/org/elasticsearch/search/fields/SearchFieldsIT.java index 4bd12c9773491..1a86b3b1da283 100644 --- a/server/src/test/java/org/elasticsearch/search/fields/SearchFieldsIT.java +++ b/server/src/test/java/org/elasticsearch/search/fields/SearchFieldsIT.java @@ -106,7 +106,8 @@ protected Map, Object>> pluginScripts() { scripts.put("doc['num1'].value * factor", vars -> { Map doc = (Map) vars.get("doc"); ScriptDocValues.Doubles num1 = (ScriptDocValues.Doubles) doc.get("num1"); - Double factor = (Double) vars.get("factor"); + Map params = (Map) vars.get("params"); + Double factor = (Double) params.get("factor"); return num1.getValue() * factor; }); From 3fb93fb6d1dfc66b09e9fa964da7735288aa16fa Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 19 Oct 2018 11:26:45 -0700 Subject: [PATCH 09/11] fix test uses of search context --- .../test/java/org/elasticsearch/client/StoredScriptsIT.java | 6 +++--- .../client/documentation/StoredScriptsDocumentationIT.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java index b15467d24ba2b..d04a8b43ebf81 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java @@ -47,7 +47,7 @@ public void testGetStoredScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score"); @@ -66,7 +66,7 @@ public void testDeleteStoredScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id); @@ -89,7 +89,7 @@ public void testPutScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); Map script = getAsMap("/_scripts/" + id); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java index 9165c5cf10d0e..bd1196b5c451c 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java @@ -307,7 +307,7 @@ public void onFailure(Exception e) { private void putStoredScript(String id, StoredScriptSource scriptSource) throws IOException { PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); } } From 669375396f8cf441165eb6ba30cadc0c457c6980 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 19 Oct 2018 12:46:33 -0700 Subject: [PATCH 10/11] fix tests to use score script, not field --- .../test/java/org/elasticsearch/client/StoredScriptsIT.java | 6 +++--- .../client/documentation/StoredScriptsDocumentationIT.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java index d04a8b43ebf81..242c2d9237dff 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java @@ -47,7 +47,7 @@ public void testGetStoredScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "score", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score"); @@ -66,7 +66,7 @@ public void testDeleteStoredScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "score", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id); @@ -89,7 +89,7 @@ public void testPutScript() throws Exception { Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "score", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); Map script = getAsMap("/_scripts/" + id); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java index bd1196b5c451c..ac4f2269f9c79 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java @@ -307,7 +307,7 @@ public void onFailure(Exception e) { private void putStoredScript(String id, StoredScriptSource scriptSource) throws IOException { PutStoredScriptRequest request = - new PutStoredScriptRequest(id, "field", new BytesArray("{}"), XContentType.JSON, scriptSource); + new PutStoredScriptRequest(id, "score", new BytesArray("{}"), XContentType.JSON, scriptSource); assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync)); } } From 30756000f41623d02aac4179fc52cfd5dd1f4460 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Sat, 20 Oct 2018 08:22:08 -0700 Subject: [PATCH 11/11] fix more test uses to score context --- .../elasticsearch/script/expression/StoredExpressionTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/StoredExpressionTests.java b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/StoredExpressionTests.java index 1877326b7d063..6cad6138acb9d 100644 --- a/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/StoredExpressionTests.java +++ b/modules/lang-expression/src/test/java/org/elasticsearch/script/expression/StoredExpressionTests.java @@ -70,7 +70,7 @@ public void testAllOpsDisabledIndexedScripts() throws IOException { .setIndices("test").setTypes("scriptTest").get(); fail("search script should have been rejected"); } catch(Exception e) { - assertThat(e.toString(), containsString("cannot execute scripts using [search] context")); + assertThat(e.toString(), containsString("cannot execute scripts using [field] context")); } try { client().prepareSearch("test")