Merge pull request #18287 from rmuir/input_goes_params
painless: remove input, support params instead
This commit is contained in:
commit
d3142e3416
|
@ -72,7 +72,7 @@ PUT hockey/player/_bulk?refresh
|
||||||
[float]
|
[float]
|
||||||
=== Accessing Doc Values from Painless
|
=== Accessing Doc Values from Painless
|
||||||
|
|
||||||
All Painless scripts take in a `Map<String,def>` of values called `input`. Document values can be accessed through another `Map<String,def>` within the `input` variable.
|
Document values can be accessed from a `Map<String,def>` named `doc`.
|
||||||
|
|
||||||
For example, the following script calculates a player's total goals. This example uses a strongly typed `int` and a `for` loop.
|
For example, the following script calculates a player's total goals. This example uses a strongly typed `int` and a `for` loop.
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ GET hockey/_search
|
||||||
"script_score": {
|
"script_score": {
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "int total = 0; for (int i = 0; i < input.doc['goals'].size(); ++i) { total += input.doc['goals'][i]; } return total;"
|
"inline": "int total = 0; for (int i = 0; i < doc['goals'].length; ++i) { total += doc['goals'][i]; } return total;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ GET hockey/_search
|
||||||
"total_goals": {
|
"total_goals": {
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "int total = 0; for (int i = 0; i < input.doc['goals'].size(); ++i) { total += input.doc['goals'][i]; } return total;"
|
"inline": "int total = 0; for (int i = 0; i < doc['goals'].length; ++i) { total += doc['goals'][i]; } return total;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ GET hockey/_search
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
|
|
||||||
The following example uses a Painless script to sort the players by their combined first and last names. The names are accessed using
|
The following example uses a Painless script to sort the players by their combined first and last names. The names are accessed using
|
||||||
`input.doc['first'].value` and `input.doc['last'].value`.
|
`doc['first'].value` and `doc['last'].value`.
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@ -131,7 +131,7 @@ GET hockey/_search
|
||||||
"order": "asc",
|
"order": "asc",
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "input.doc['first'].value + ' ' + input.doc['last'].value"
|
"inline": "doc['first'].value + ' ' + doc['last'].value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ GET hockey/_search
|
||||||
[float]
|
[float]
|
||||||
=== Updating Fields with Painless
|
=== Updating Fields with Painless
|
||||||
|
|
||||||
You can also easily update fields. You access the original source for a field as `input.ctx._source.<field-name>`.
|
You can also easily update fields. You access the original source for a field as `ctx._source.<field-name>`.
|
||||||
|
|
||||||
First, let's look at the source data for a player by submitting the following request:
|
First, let's look at the source data for a player by submitting the following request:
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ GET hockey/_search
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
// CONSOLE
|
// CONSOLE
|
||||||
|
|
||||||
To change player 1's last name to `hockey`, simply set `input.ctx._source.last` to the new value:
|
To change player 1's last name to `hockey`, simply set `ctx._source.last` to the new value:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@ -171,7 +171,7 @@ POST hockey/player/1/_update
|
||||||
{
|
{
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "input.ctx._source.last = input.last",
|
"inline": "ctx._source.last = params.last",
|
||||||
"params": {
|
"params": {
|
||||||
"last": "hockey"
|
"last": "hockey"
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ POST hockey/player/1/_update
|
||||||
{
|
{
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "input.ctx._source.last = input.last input.ctx._source.nick = input.nick",
|
"inline": "ctx._source.last = params.last ctx._source.nick = params.nick",
|
||||||
"params": {
|
"params": {
|
||||||
"last": "gaudreau",
|
"last": "gaudreau",
|
||||||
"nick": "hockey"
|
"nick": "hockey"
|
||||||
|
|
|
@ -94,10 +94,10 @@ class Analyzer extends PainlessParserBaseVisitor<Void> {
|
||||||
utility.incrementScope();
|
utility.incrementScope();
|
||||||
utility.addVariable(null, "#this", definition.execType);
|
utility.addVariable(null, "#this", definition.execType);
|
||||||
//
|
//
|
||||||
// reserved words parameters.
|
// reserved words.
|
||||||
//
|
//
|
||||||
// input map of variables passed to the script. TODO: rename to 'params' since that will be its use
|
// input map of parameters passed to the script.
|
||||||
metadata.inputValueSlot = utility.addVariable(null, "input", definition.smapType).slot;
|
metadata.paramsValueSlot = utility.addVariable(null, "params", definition.smapType).slot;
|
||||||
// scorer parameter passed to the script. internal use only.
|
// scorer parameter passed to the script. internal use only.
|
||||||
metadata.scorerValueSlot = utility.addVariable(null, "#scorer", definition.objectType).slot;
|
metadata.scorerValueSlot = utility.addVariable(null, "#scorer", definition.objectType).slot;
|
||||||
// doc parameter passed to the script.
|
// doc parameter passed to the script.
|
||||||
|
|
|
@ -49,5 +49,5 @@ public abstract class Executable {
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Object execute(Map<String, Object> input, Scorer scorer, LeafDocLookup doc, Object value);
|
public abstract Object execute(Map<String, Object> params, Scorer scorer, LeafDocLookup doc, Object value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,7 @@ class Metadata {
|
||||||
* Used to determine what slot the input variable is stored in. This is used in the {@link Writer} whenever
|
* Used to determine what slot the input variable is stored in. This is used in the {@link Writer} whenever
|
||||||
* the input variable is accessed.
|
* the input variable is accessed.
|
||||||
*/
|
*/
|
||||||
int inputValueSlot = -1;
|
int paramsValueSlot = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to determine what slot the Scorer variable is stored in. This is used in the {@link Writer} to load
|
* Used to determine what slot the Scorer variable is stored in. This is used in the {@link Writer} to load
|
||||||
|
|
|
@ -162,7 +162,7 @@ class Writer extends PainlessParserBaseVisitor<Void> {
|
||||||
if (metadata.ctxValueUsed) {
|
if (metadata.ctxValueUsed) {
|
||||||
// if the _ctx value is used, we do this once:
|
// if the _ctx value is used, we do this once:
|
||||||
// final Map<String,Object> ctx = input.get("ctx");
|
// final Map<String,Object> ctx = input.get("ctx");
|
||||||
execute.visitVarInsn(Opcodes.ALOAD, metadata.inputValueSlot);
|
execute.visitVarInsn(Opcodes.ALOAD, metadata.paramsValueSlot);
|
||||||
execute.push("ctx");
|
execute.push("ctx");
|
||||||
execute.invokeInterface(WriterConstants.MAP_TYPE, WriterConstants.MAP_GET);
|
execute.invokeInterface(WriterConstants.MAP_TYPE, WriterConstants.MAP_GET);
|
||||||
execute.visitVarInsn(Opcodes.ASTORE, metadata.ctxValueSlot);
|
execute.visitVarInsn(Opcodes.ASTORE, metadata.ctxValueSlot);
|
||||||
|
|
|
@ -100,11 +100,11 @@ public class BasicExpressionTests extends ScriptTestCase {
|
||||||
*/
|
*/
|
||||||
public void testBoxing() {
|
public void testBoxing() {
|
||||||
// return
|
// return
|
||||||
assertEquals(4, exec("return input.get(\"x\");", Collections.singletonMap("x", 4)));
|
assertEquals(4, exec("return params.get(\"x\");", Collections.singletonMap("x", 4)));
|
||||||
// assignment
|
// assignment
|
||||||
assertEquals(4, exec("int y = (Integer)input.get(\"x\"); return y;", Collections.singletonMap("x", 4)));
|
assertEquals(4, exec("int y = (Integer)params.get(\"x\"); return y;", Collections.singletonMap("x", 4)));
|
||||||
// comparison
|
// comparison
|
||||||
assertEquals(true, exec("return 5 > (Integer)input.get(\"x\");", Collections.singletonMap("x", 4)));
|
assertEquals(true, exec("return 5 > (Integer)params.get(\"x\");", Collections.singletonMap("x", 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBool() {
|
public void testBool() {
|
||||||
|
|
|
@ -46,12 +46,12 @@ public class ScriptEngineTests extends ScriptTestCase {
|
||||||
obj1.put("l", Arrays.asList("2", "1"));
|
obj1.put("l", Arrays.asList("2", "1"));
|
||||||
vars.put("obj1", obj1);
|
vars.put("obj1", obj1);
|
||||||
|
|
||||||
Object value = exec("return input.get(\"obj1\");", vars);
|
Object value = exec("return params['obj1'];", vars);
|
||||||
obj1 = (Map<String, Object>)value;
|
obj1 = (Map<String, Object>)value;
|
||||||
assertEquals("value1", obj1.get("prop1"));
|
assertEquals("value1", obj1.get("prop1"));
|
||||||
assertEquals("value2", ((Map<String, Object>) obj1.get("obj2")).get("prop2"));
|
assertEquals("value2", ((Map<String, Object>) obj1.get("obj2")).get("prop2"));
|
||||||
|
|
||||||
value = exec("return ((List)((Map<String, Object>)input.get(\"obj1\")).get(\"l\")).get(0);", vars);
|
value = exec("return params.obj1.l.0;", vars);
|
||||||
assertEquals("2", value);
|
assertEquals("2", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,15 +65,15 @@ public class ScriptEngineTests extends ScriptTestCase {
|
||||||
obj1.put("obj2", obj2);
|
obj1.put("obj2", obj2);
|
||||||
vars.put("l", Arrays.asList("1", "2", "3", obj1));
|
vars.put("l", Arrays.asList("1", "2", "3", obj1));
|
||||||
|
|
||||||
assertEquals(4, exec("return ((List)input.get(\"l\")).size();", vars));
|
assertEquals(4, exec("return params.l.size();", vars));
|
||||||
assertEquals("1", exec("return ((List)input.get(\"l\")).get(0);", vars));
|
assertEquals("1", exec("return params.l.0;", vars));
|
||||||
|
|
||||||
Object value = exec("return ((List)input.get(\"l\")).get(3);", vars);
|
Object value = exec("return params.l.3;", vars);
|
||||||
obj1 = (Map<String, Object>)value;
|
obj1 = (Map<String, Object>)value;
|
||||||
assertEquals("value1", obj1.get("prop1"));
|
assertEquals("value1", obj1.get("prop1"));
|
||||||
assertEquals("value2", ((Map<String, Object>)obj1.get("obj2")).get("prop2"));
|
assertEquals("value2", ((Map<String, Object>)obj1.get("obj2")).get("prop2"));
|
||||||
|
|
||||||
assertEquals("value1", exec("return ((Map<String, Object>)((List)input.get(\"l\")).get(3)).get(\"prop1\");", vars));
|
assertEquals("value1", exec("return params.l.3.prop1;", vars));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testChangingVarsCrossExecution1() {
|
public void testChangingVarsCrossExecution1() {
|
||||||
|
@ -82,7 +82,7 @@ public class ScriptEngineTests extends ScriptTestCase {
|
||||||
vars.put("ctx", ctx);
|
vars.put("ctx", ctx);
|
||||||
|
|
||||||
Object compiledScript = scriptEngine.compile(
|
Object compiledScript = scriptEngine.compile(
|
||||||
"return ((Map<String, Object>)input.get(\"ctx\")).get(\"value\");", Collections.emptyMap());
|
"return ctx.value;", Collections.emptyMap());
|
||||||
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
||||||
"testChangingVarsCrossExecution1", "painless", compiledScript), vars);
|
"testChangingVarsCrossExecution1", "painless", compiledScript), vars);
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public class ScriptEngineTests extends ScriptTestCase {
|
||||||
|
|
||||||
public void testChangingVarsCrossExecution2() {
|
public void testChangingVarsCrossExecution2() {
|
||||||
Map<String, Object> vars = new HashMap<>();
|
Map<String, Object> vars = new HashMap<>();
|
||||||
Object compiledScript = scriptEngine.compile("return input.get(\"value\");", Collections.emptyMap());
|
Object compiledScript = scriptEngine.compile("return params['value'];", Collections.emptyMap());
|
||||||
|
|
||||||
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
ExecutableScript script = scriptEngine.executable(new CompiledScript(ScriptService.ScriptType.INLINE,
|
||||||
"testChangingVarsCrossExecution2", "painless", compiledScript), vars);
|
"testChangingVarsCrossExecution2", "painless", compiledScript), vars);
|
||||||
|
|
|
@ -26,7 +26,7 @@ import java.util.Collections;
|
||||||
public class WhenThingsGoWrongTests extends ScriptTestCase {
|
public class WhenThingsGoWrongTests extends ScriptTestCase {
|
||||||
public void testNullPointer() {
|
public void testNullPointer() {
|
||||||
expectThrows(NullPointerException.class, () -> {
|
expectThrows(NullPointerException.class, () -> {
|
||||||
exec("int x = (int) ((Map) input).get(\"missing\"); return x;");
|
exec("int x = params['missing']; return x;");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
script: "1"
|
script: "1"
|
||||||
body:
|
body:
|
||||||
lang: painless
|
lang: painless
|
||||||
script: "ctx._source.foo = input.bar"
|
script: "ctx._source.foo = params.bar"
|
||||||
params: { bar: 'xxx' }
|
params: { bar: 'xxx' }
|
||||||
|
|
||||||
- match: { _index: test_1 }
|
- match: { _index: test_1 }
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
put_script:
|
put_script:
|
||||||
id: "1"
|
id: "1"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
body: { "script": "_score * doc[\"myParent.weight\"].value" }
|
body: { "script": "_score * doc['myParent.weight'].value" }
|
||||||
- match: { acknowledged: true }
|
- match: { acknowledged: true }
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
- match: { found: true }
|
- match: { found: true }
|
||||||
- match: { lang: painless }
|
- match: { lang: painless }
|
||||||
- match: { _id: "1" }
|
- match: { _id: "1" }
|
||||||
- match: { "script": "_score * doc[\"myParent.weight\"].value" }
|
- match: { "script": "_score * doc['myParent.weight'].value" }
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
catch: missing
|
catch: missing
|
||||||
|
@ -44,11 +44,11 @@
|
||||||
put_script:
|
put_script:
|
||||||
id: "1"
|
id: "1"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
body: { "script": "_score * foo bar + doc[\"myParent.weight\"].value" }
|
body: { "script": "_score * foo bar + doc['myParent.weight'].value" }
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
catch: /Unable.to.parse.*/
|
catch: /Unable.to.parse.*/
|
||||||
put_script:
|
put_script:
|
||||||
id: "1"
|
id: "1"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
body: { "script": "_score * foo bar + doc[\"myParent.weight\"].value" }
|
body: { "script": "_score * foo bar + doc['myParent.weight'].value" }
|
||||||
|
|
|
@ -28,7 +28,7 @@ setup:
|
||||||
script_fields:
|
script_fields:
|
||||||
bar:
|
bar:
|
||||||
script:
|
script:
|
||||||
inline: "doc['foo'].value + input.x;"
|
inline: "doc['foo'].value + params.x;"
|
||||||
lang: painless
|
lang: painless
|
||||||
params:
|
params:
|
||||||
x: "bbb"
|
x: "bbb"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
type: test
|
type: test
|
||||||
id: 1
|
id: 1
|
||||||
body:
|
body:
|
||||||
script: "ctx._source.foo = input.bar"
|
script: "ctx._source.foo = params.bar"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
params: { bar: 'xxx' }
|
params: { bar: 'xxx' }
|
||||||
upsert: { foo: baz }
|
upsert: { foo: baz }
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
type: test
|
type: test
|
||||||
id: 1
|
id: 1
|
||||||
body:
|
body:
|
||||||
script: "ctx._source.foo = input.bar"
|
script: "ctx._source.foo = params.bar"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
params: { bar: 'xxx' }
|
params: { bar: 'xxx' }
|
||||||
upsert: { foo: baz }
|
upsert: { foo: baz }
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
type: test
|
type: test
|
||||||
id: 2
|
id: 2
|
||||||
body:
|
body:
|
||||||
script: "ctx._source.foo = input.bar"
|
script: "ctx._source.foo = params.bar"
|
||||||
lang: "painless"
|
lang: "painless"
|
||||||
params: { bar: 'xxx' }
|
params: { bar: 'xxx' }
|
||||||
upsert: { foo: baz }
|
upsert: { foo: baz }
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
query:
|
query:
|
||||||
script:
|
script:
|
||||||
script:
|
script:
|
||||||
inline: "doc['num1'].value > input.param1;"
|
inline: "doc['num1'].value > params.param1;"
|
||||||
lang: painless
|
lang: painless
|
||||||
params:
|
params:
|
||||||
param1: 1
|
param1: 1
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
query:
|
query:
|
||||||
script:
|
script:
|
||||||
script:
|
script:
|
||||||
inline: "doc['num1'].value > input.param1;"
|
inline: "doc['num1'].value > params.param1;"
|
||||||
lang: painless
|
lang: painless
|
||||||
params:
|
params:
|
||||||
param1: -1
|
param1: -1
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
"script_score": {
|
"script_score": {
|
||||||
"script": {
|
"script": {
|
||||||
"lang": "painless",
|
"lang": "painless",
|
||||||
"inline": "input.param1 * input.param2 * _score",
|
"inline": "params.param1 * params.param2 * _score",
|
||||||
"params": {
|
"params": {
|
||||||
"param1": 2,
|
"param1": 2,
|
||||||
"param2": 2
|
"param2": 2
|
||||||
|
|
Loading…
Reference in New Issue