diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml index bb01fc3eca154..abdf09fa76819 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml @@ -118,6 +118,39 @@ setup: index: "my-index" - match: { result: [ false, false, true, true ] } +--- +"Execute with boolean field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(false) < params.max_rank);" + params: + max_rank: 5.0 + context: "boolean_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ true ] } + + +--- +"Execute with boolean field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(false) < params.max_rank); emit(false); emit(false); emit(true);" + params: + max_rank: 5.0 + context: "boolean_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ false, false, true, true ] } + --- "Execute with date field context (single-value)": - do: @@ -147,6 +180,35 @@ setup: index: "my-index" - match: { result: [ "2015-01-01T12:10:30.000Z", "2010-11-30T13:14:35.000Z" ] } +--- +"Execute with date field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('date').getValue(0).toInstant().toEpochMilli())" + context: "date_field" + context_setup: + document: + date: "2015-01-01T12:10:30Z" + index: "my-index" + - match: { result: [ "2015-01-01T12:10:30.000Z" ] } + +--- +"Execute with date field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('date0').values[0].toInstant().toEpochMilli()); emit(field('date1').values[0].toInstant().toEpochMilli());" + context: "date_field" + context_setup: + document: + date0: "2015-01-01T12:10:30Z" + date1: "2010-11-30T13:14:35Z" + index: "my-index" + - match: { result: [ "2015-01-01T12:10:30.000Z", "2010-11-30T13:14:35.000Z" ] } + --- "Execute with double field context (single-value)": - do: @@ -179,6 +241,38 @@ setup: index: "my-index" - match: { result: [ 20.0, 400.0, 55.0 ] } +--- +"Execute with double field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(0.0) * params.max_rank)" + params: + max_rank: 5.0 + context: "double_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ 20.0 ] } + +--- +"Execute with double field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(0.0) * params.max_rank); emit(400.0); emit(55.0)" + params: + max_rank: 5.0 + context: "double_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ 20.0, 400.0, 55.0 ] } + --- "Execute with geo point field context (single-value)": - skip: @@ -219,6 +313,47 @@ setup: - close_to: { result.1.coordinates.1: { value: 41.0, error: 0.00001 } } - match: { result.1.type: "Point" } +--- +"Execute with geo point field context (single-value, fields api)": + - skip: + features: close_to + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('point').getValue(null).lat + 1.0, field('point').getValue(null).lon - 1.0)" + context: "geo_point_field" + context_setup: + document: + point: "30.0,40.0" + index: "my-index" + - close_to: { result.0.coordinates.0: { value: 39.0, error: 0.00001 } } + - close_to: { result.0.coordinates.1: { value: 31.0, error: 0.00001 } } + - match: { result.0.type: "Point" } + +--- +"Execute with geo point field context (multi-value, fields api)": + - skip: + features: close_to + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('p0').values[0].lat + 1.0, field('p0').values[0].lon - 1.0); + emit(field('p1').values[0].lat + 1.0, field('p1').values[0].lon - 1.0)" + context: "geo_point_field" + context_setup: + document: + p0: "30.0,40.0" + p1: "40.0,30.0" + index: "my-index" + - close_to: { result.0.coordinates.0: { value: 39.0, error: 0.00001 } } + - close_to: { result.0.coordinates.1: { value: 31.0, error: 0.00001 } } + - match: { result.0.type: "Point" } + - close_to: { result.1.coordinates.0: { value: 29.0, error: 0.00001 } } + - close_to: { result.1.coordinates.1: { value: 41.0, error: 0.00001 } } + - match: { result.1.type: "Point" } + --- "Execute with ip field context (single-value)": - do: @@ -247,6 +382,36 @@ setup: index: "my-index" - match: { result: [ "2001:db8::8a2e:370:7333", "192.168.1.254", "2001:db8::8a2e:370:7334" ] } +--- +"Execute with ip field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('ip').getValue('0.0.0.0'));" + context: "ip_field" + context_setup: + document: + ip: "192.168.1.254" + index: "my-index" + - match: { result: [ "192.168.1.254" ] } + +--- +"Execute with ip field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit('2001:0db8:0000:0000:0000:8a2e:0370:7333'); + emit(field('ip').getValue('0.0.0.0')); + emit('2001:db8::8a2e:370:7334')" + context: "ip_field" + context_setup: + document: + ip: "192.168.1.254" + index: "my-index" + - match: { result: [ "2001:db8::8a2e:370:7333", "192.168.1.254", "2001:db8::8a2e:370:7334" ] } + --- "Execute with long field context (single-value)": - do: @@ -279,6 +444,38 @@ setup: index: "my-index" - match: { result: [ 20, 35, 0, -90, 20 ] } +--- +"Execute with long field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(0L) * (long)params.max_rank)" + params: + max_rank: 5.0 + context: "long_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ 20 ] } + +--- +"Execute with long field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('rank').getValue(0L) * (long)params.max_rank); emit(35); emit(0); emit(-90); emit(20);" + params: + max_rank: 5.0 + context: "long_field" + context_setup: + document: + rank: 4 + index: "my-index" + - match: { result: [ 20, 35, 0, -90, 20 ] } + --- "Execute with keyword field context (single-value)": - do: @@ -308,6 +505,35 @@ setup: - match: { result.0: "my_keyword" } - match: { result.1: "my_keyword_test" } +--- +"Execute with keyword field context (single-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('keyword').getValue(''));" + context: "keyword_field" + context_setup: + document: + keyword: "my_keyword" + index: "my-index" + - match: { result.0: "my_keyword" } + +--- +"Execute with keyword field context (multi-value, fields api)": + - do: + scripts_painless_execute: + body: + script: + source: "emit(field('keyword').getValue('')); emit(field('keyword').getValue('') + '_test');" + context: "keyword_field" + context_setup: + document: + keyword: "my_keyword" + index: "my-index" + - match: { result.0: "my_keyword" } + - match: { result.1: "my_keyword_test" } + --- "Execute against an empty index with no mappings": - do: diff --git a/server/src/main/java/org/elasticsearch/script/AbstractFieldScript.java b/server/src/main/java/org/elasticsearch/script/AbstractFieldScript.java index 77f93cdf0e2ad..524cb1b5ece00 100644 --- a/server/src/main/java/org/elasticsearch/script/AbstractFieldScript.java +++ b/server/src/main/java/org/elasticsearch/script/AbstractFieldScript.java @@ -27,7 +27,7 @@ * Abstract base for scripts to execute to build scripted fields. Inspired by * {@link AggregationScript} but hopefully with less historical baggage. */ -public abstract class AbstractFieldScript { +public abstract class AbstractFieldScript extends DocBasedScript { /** * The maximum number of values a script should be allowed to emit. */ @@ -73,6 +73,8 @@ static ScriptContext newContext(String name, Class factoryClass) { protected final LeafSearchLookup leafSearchLookup; public AbstractFieldScript(String fieldName, Map params, SearchLookup searchLookup, LeafReaderContext ctx) { + super(new DocValuesDocReader(searchLookup, ctx)); + this.fieldName = fieldName; this.leafSearchLookup = searchLookup.getLeafSearchLookup(ctx); params = new HashMap<>(params);