mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 09:28:55 -04:00
Runtime fields to optionally ignore script errors (#92380)
Currently Elasticsearch always returns a shard failure once a runtime error arises from using a runtime field, the exception being script-less runtime fields. This also means that execution of the query for that shard stops, which is okay for development and exploration. In a production scenario, however, it is often desirable to ignore runtime errors and continue with the query execution. This change adds a new a new on_script_error parameter to runtime field definitions similar to the already existing parameter for index-time scripted fields. When `on_script_error` is set to `continue`, errors from script execution are effectively ignored. This means affected documents don't show up in query results, but also don't prevent other matches from the same shard. Runtime fields accessed through the fields API don't return values on errors, aggregations will ignore documents that throw errors. Note that this change affects scripted runtime fields only, while leaving default behaviour untouched. Also, ignored errors are not reported back to users for now. Relates to #72143
This commit is contained in:
parent
3bbf202843
commit
8067f01d48
78 changed files with 2184 additions and 303 deletions
5
docs/changelog/92380.yaml
Normal file
5
docs/changelog/92380.yaml
Normal file
|
@ -0,0 +1,5 @@
|
|||
pr: 92380
|
||||
summary: Add option to allow script errors on runtime fields
|
||||
area: Search
|
||||
type: enhancement
|
||||
issues: []
|
|
@ -53,7 +53,7 @@ combined use less resources and reduce your operating costs.
|
|||
Runtime fields can replace many of the ways you can use scripting with the
|
||||
`_search` API. How you use a runtime field is impacted by the number of
|
||||
documents that the included script runs against. For example, if you're using
|
||||
the `fields` parameter on the `_search` API to
|
||||
the `fields` parameter on the `_search` API to
|
||||
<<runtime-retrieving-fields,retrieve the values of a runtime field>>, the script
|
||||
runs only against the top hits just like script fields do.
|
||||
|
||||
|
@ -77,7 +77,7 @@ If you move a script from any of these sections in a search request to a
|
|||
runtime field that is computing values from the same number of documents, the
|
||||
performance should be about the same. The performance for these features is
|
||||
largely dependent upon the calculations that the included script is running and
|
||||
how many documents the script runs against.
|
||||
how many documents the script runs against.
|
||||
|
||||
[discrete]
|
||||
[[runtime-compromises]]
|
||||
|
@ -88,9 +88,9 @@ the runtime script.
|
|||
|
||||
To balance search performance and flexibility, index fields that you'll
|
||||
frequently search for and filter on, such as a timestamp. {es} automatically
|
||||
uses these indexed fields first when running a query, resulting in a fast
|
||||
response time. You can then use runtime fields to limit the number of fields
|
||||
that {es} needs to calculate values for. Using indexed fields in tandem with
|
||||
uses these indexed fields first when running a query, resulting in a fast
|
||||
response time. You can then use runtime fields to limit the number of fields
|
||||
that {es} needs to calculate values for. Using indexed fields in tandem with
|
||||
runtime fields provides flexibility in the data that you index and how you
|
||||
define queries for other fields.
|
||||
|
||||
|
@ -111,7 +111,7 @@ You map runtime fields by adding a `runtime` section under the mapping
|
|||
definition and defining
|
||||
<<modules-scripting-using,a Painless script>>. This script has access to the
|
||||
entire context of a document, including the original `_source` via `params._source`
|
||||
and any mapped fields plus their values. At query time, the script runs and
|
||||
and any mapped fields plus their values. At query time, the script runs and
|
||||
generates values for each scripted field that is required for the query.
|
||||
|
||||
.Emitting runtime field values
|
||||
|
@ -227,6 +227,16 @@ with `params._source` (such as `params._source.day_of_week`). For simplicity,
|
|||
defining a runtime field in the mapping definition without a script is the
|
||||
recommended option, whenever possible.
|
||||
|
||||
[[runtime-errorhandling]]
|
||||
==== Ignoring script errors on runtime fields
|
||||
|
||||
Scripts can throw errors at runtime, e.g. on accessing missing or invalid values
|
||||
in documents or because of performing invalid operations. The `on_script_error`
|
||||
parameter can be used to control error behaviour when this happens. Setting this
|
||||
parameter to `continue` will have the effect of silently ignoring all errors on
|
||||
this runtime field. The default `fail` value will cause a shard failure which
|
||||
gets reported in the search response.
|
||||
|
||||
[[runtime-updating-scripts]]
|
||||
==== Updating and removing runtime fields
|
||||
|
||||
|
@ -932,14 +942,14 @@ can define runtime fields in the
|
|||
decide to index a runtime field for greater performance, just move the full
|
||||
runtime field definition (including the script) to the context of an index
|
||||
mapping. {es} automatically uses these indexed fields to drive queries,
|
||||
resulting in a fast response time. This capability means you can write a
|
||||
resulting in a fast response time. This capability means you can write a
|
||||
script only once, and apply it to any context that supports runtime fields.
|
||||
|
||||
NOTE: Indexing a `composite` runtime field is currently not supported.
|
||||
|
||||
You can then use runtime fields to limit the number of fields that {es} needs
|
||||
to calculate values for. Using indexed fields in tandem with runtime fields
|
||||
provides flexibility in the data that you index and how you define queries for
|
||||
You can then use runtime fields to limit the number of fields that {es} needs
|
||||
to calculate values for. Using indexed fields in tandem with runtime fields
|
||||
provides flexibility in the data that you index and how you define queries for
|
||||
other fields.
|
||||
|
||||
IMPORTANT: After indexing a runtime field, you cannot update the included
|
||||
|
@ -1417,9 +1427,9 @@ GET my-index-000001/_search
|
|||
|
||||
[[runtime-examples-grok-composite]]
|
||||
==== Define a composite runtime field
|
||||
You can also define a _composite_ runtime field to emit multiple fields from a
|
||||
single script. You can define a set of typed subfields and emit a map of
|
||||
values. At search time, each subfield retrieves the value associated with
|
||||
You can also define a _composite_ runtime field to emit multiple fields from a
|
||||
single script. You can define a set of typed subfields and emit a map of
|
||||
values. At search time, each subfield retrieves the value associated with
|
||||
their name in the map. This means that you only need to specify your grok
|
||||
pattern one time and can return multiple values:
|
||||
|
||||
|
@ -1467,11 +1477,11 @@ GET my-index-000001/_search
|
|||
----
|
||||
// TEST[continued]
|
||||
|
||||
The API returns the following result. Because `http` is a `composite` runtime
|
||||
The API returns the following result. Because `http` is a `composite` runtime
|
||||
field, the response includes each of the sub-fields under `fields`, including
|
||||
any associated values that match the query. Without building your data structure
|
||||
any associated values that match the query. Without building your data structure
|
||||
in advance, you can search and explore your data in meaningful ways to
|
||||
experiment and determine which fields to index.
|
||||
experiment and determine which fields to index.
|
||||
|
||||
[source,console-result]
|
||||
----
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.elasticsearch.index.Index;
|
|||
import org.elasticsearch.index.IndexService;
|
||||
import org.elasticsearch.index.mapper.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||
import org.elasticsearch.index.mapper.SourceToParse;
|
||||
import org.elasticsearch.index.query.AbstractQueryBuilder;
|
||||
|
@ -557,7 +558,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
BooleanFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
BooleanFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
BooleanFieldScript booleanFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<Boolean> booleans = new ArrayList<>();
|
||||
|
@ -571,7 +573,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
DateFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup(),
|
||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER
|
||||
DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER,
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
DateFieldScript dateFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<String> dates = new ArrayList<>();
|
||||
|
@ -584,7 +587,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
DoubleFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
DoubleFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
DoubleFieldScript doubleFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<Double> doubles = new ArrayList<>();
|
||||
|
@ -597,7 +601,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
GeoPointFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
GeoPointFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
GeoPointFieldScript geoPointFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<GeoPoint> points = new ArrayList<>();
|
||||
|
@ -615,7 +620,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
IpFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
IpFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
IpFieldScript ipFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<String> ips = new ArrayList<>();
|
||||
|
@ -634,7 +640,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
LongFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
LongFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
LongFieldScript longFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<Long> longs = new ArrayList<>();
|
||||
|
@ -647,7 +654,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
StringFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
StringFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
StringFieldScript stringFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
List<String> keywords = new ArrayList<>();
|
||||
|
@ -660,7 +668,8 @@ public class PainlessExecuteAction extends ActionType<PainlessExecuteAction.Resp
|
|||
CompositeFieldScript.LeafFactory leafFactory = factory.newFactory(
|
||||
CompositeFieldScript.CONTEXT.name,
|
||||
request.getScript().getParams(),
|
||||
context.lookup()
|
||||
context.lookup(),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
CompositeFieldScript compositeFieldScript = leafFactory.newInstance(leafReaderContext);
|
||||
compositeFieldScript.runForDoc(0);
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: composite
|
||||
on_script_error: continue
|
||||
script:
|
||||
source: |
|
||||
if (doc["message"].value.equals("fail")) throw new Exception("error");
|
||||
emit('msg', doc['message'].value);
|
||||
fields:
|
||||
msg:
|
||||
type: keyword
|
||||
rtf_strict:
|
||||
type: composite
|
||||
on_script_error: fail
|
||||
script:
|
||||
source: |
|
||||
if (doc["message"].value.equals("fail")) throw new Exception("error");
|
||||
emit('msg', doc['message'].value);
|
||||
fields:
|
||||
msg:
|
||||
type: keyword
|
||||
properties:
|
||||
timestamp:
|
||||
type: date
|
||||
message:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: test
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"timestamp": "1998-04-30T14:30:17-05:00", "message" : "this is okay"}
|
||||
{"index":{}}
|
||||
{"timestamp": "1998-04-30T14:30:53-05:00", "message" : "fail"}
|
||||
|
||||
---
|
||||
"query with continue on error":
|
||||
- do:
|
||||
search:
|
||||
index: test
|
||||
body:
|
||||
query:
|
||||
term:
|
||||
rtf.msg: "this is okay"
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0._source.message: "this is okay"}
|
||||
|
||||
---
|
||||
"query with fail on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: test
|
||||
body:
|
||||
query:
|
||||
term:
|
||||
rtf_strict.msg: "this is okay"
|
||||
|
||||
---
|
||||
"query with search time field":
|
||||
- do:
|
||||
search:
|
||||
index: test
|
||||
body:
|
||||
query:
|
||||
term:
|
||||
rtf_search.msg: "this is okay"
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: composite
|
||||
on_script_error: continue
|
||||
script:
|
||||
source: |
|
||||
if (doc["message"].value.equals("fail")) throw new Exception("error");
|
||||
emit('msg', doc['message'].value);
|
||||
fields:
|
||||
msg:
|
||||
type: keyword
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0._source.message: "this is okay"}
|
||||
|
||||
---
|
||||
fetch:
|
||||
- do:
|
||||
search:
|
||||
index: test
|
||||
body:
|
||||
sort: timestamp
|
||||
fields:
|
||||
- message
|
||||
- rtf.msg
|
||||
- match: {hits.total.value: 2}
|
||||
- match: {hits.hits.0.fields.message: ["this is okay"] }
|
||||
- match: {hits.hits.0.fields.rtf\.msg: ["this is okay"] }
|
||||
- match: {hits.hits.1.fields.message: ["fail"] }
|
||||
- is_false: hits.hits.1.fields.rtf.msg
|
||||
|
||||
---
|
||||
"terms agg":
|
||||
- do:
|
||||
search:
|
||||
index: test
|
||||
body:
|
||||
aggs:
|
||||
messages:
|
||||
terms:
|
||||
field: rtf.msg
|
||||
- match: { hits.total.value: 2}
|
||||
- length: { aggregations.messages.buckets: 1 }
|
||||
- match: { aggregations.messages.buckets.0.key: "this is okay" }
|
||||
- match: { aggregations.messages.buckets.0.doc_count: 1 }
|
|
@ -0,0 +1,216 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
mappings:
|
||||
runtime:
|
||||
first_char:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
on_script_error: continue
|
||||
first_char_strict_error:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
on_script_error: fail
|
||||
properties:
|
||||
name:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"name": "foo"}
|
||||
{"index":{}}
|
||||
{"name": ""}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char: "f"
|
||||
fields: [ name, first_char ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.first_char: [ f ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char_strict_error: "f"
|
||||
fields: [ name, first_char_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: first_char
|
||||
- length: { aggregations.firstchar.buckets: 1 }
|
||||
- match: { aggregations.firstchar.buckets.0.key: "f" }
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: first_char_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, first_char ]
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.first_char: [ f ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
- is_false: hits.hits.1.fields.first_char
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, first_char_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: first_char
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: first_char_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char_search: "f"
|
||||
fields: [ name, first_char_search ]
|
||||
runtime_mappings:
|
||||
first_char_search:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.first_char_search: [ f ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char_search: "f"
|
||||
fields: [ name, first_char_search ]
|
||||
runtime_mappings:
|
||||
first_char_search:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
on_script_error: fail
|
||||
|
||||
---
|
||||
"Change error behaviour for lenient runtime field":
|
||||
|
||||
- do:
|
||||
indices.put_mapping:
|
||||
index: testindex
|
||||
body:
|
||||
runtime:
|
||||
first_char_variant:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char_variant: "f"
|
||||
|
||||
- do:
|
||||
indices.put_mapping:
|
||||
index: testindex
|
||||
body:
|
||||
runtime:
|
||||
first_char_variant:
|
||||
type: keyword
|
||||
script: |
|
||||
emit(doc['name'].value.substring(0,1));
|
||||
on_script_error: continue
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
first_char_variant: "f"
|
||||
fields: [ name, first_char_variant ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.first_char_variant: [ f ] }
|
|
@ -0,0 +1,176 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: long
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: continue
|
||||
rtf_strict_error:
|
||||
type: long
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: fail
|
||||
properties:
|
||||
name:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"name": "foo"}
|
||||
{"index":{}}
|
||||
{"name": ""}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf: 3
|
||||
fields: [ name, rtf ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ 3 ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_strict_error: 3
|
||||
fields: [ name, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf
|
||||
- length: { aggregations.firstchar.buckets: 1 }
|
||||
- match: { aggregations.firstchar.buckets.0.key: 3 }
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, rtf ]
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ 3 ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
- is_false: hits.hits.1.fields.rtf
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: rtf
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: rtf_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: 3
|
||||
fields: [ name, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: long
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf_search: [ 3 ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: 3
|
||||
fields: [ name, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: long
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: fail
|
|
@ -0,0 +1,176 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: double
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: continue
|
||||
rtf_strict_error:
|
||||
type: double
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: fail
|
||||
properties:
|
||||
name:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"name": "foo"}
|
||||
{"index":{}}
|
||||
{"name": ""}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf: 3
|
||||
fields: [ name, rtf ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ 3.0 ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_strict_error: 3
|
||||
fields: [ name, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf
|
||||
- length: { aggregations.firstchar.buckets: 1 }
|
||||
- match: { aggregations.firstchar.buckets.0.key: 3.0 }
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, rtf ]
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ 3.0 ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
- is_false: hits.hits.1.fields.rtf
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: rtf
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.1.fields.name: [ "" ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ name ]
|
||||
sort: rtf_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: 3
|
||||
fields: [ name, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: double
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.name: [ foo ] }
|
||||
- match: { hits.hits.0.fields.rtf_search: [ 3.0 ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: 3
|
||||
fields: [ name, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: double
|
||||
script: |
|
||||
if(doc['name'].value.equals("")) throw new Exception("empty");
|
||||
emit(doc['name'].value.length());
|
||||
on_script_error: fail
|
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: date
|
||||
format: yyyy-MM-dd
|
||||
script: |
|
||||
if(doc['millis_since_epoch'].value < 0) throw new Exception("date before 1970");
|
||||
emit(doc['millis_since_epoch'].value);
|
||||
on_script_error: continue
|
||||
rtf_strict_error:
|
||||
type: date
|
||||
format: yyyy-MM-dd
|
||||
script: |
|
||||
if(doc['millis_since_epoch'].value < 0) throw new Exception("date before 1970");
|
||||
emit(doc['millis_since_epoch'].value);
|
||||
on_script_error: fail
|
||||
properties:
|
||||
millis_since_epoch:
|
||||
type: long
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"millis_since_epoch": 1671033474411}
|
||||
{"index":{}}
|
||||
{"millis_since_epoch": -1}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
range:
|
||||
rtf:
|
||||
gte: "2022-12-14"
|
||||
fields: [ millis_since_epoch, rtf ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.millis_since_epoch: [ 1671033474411 ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ "2022-12-14" ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
range:
|
||||
rtf_strict_error:
|
||||
gte: "2022-12-14"
|
||||
fields: [ millis_since_epoch, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf
|
||||
- length: { aggregations.firstchar.buckets: 1 }
|
||||
- match: { aggregations.firstchar.buckets.0.key_as_string: "2022-12-14" }
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
firstchar:
|
||||
terms:
|
||||
field: rtf_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ millis_since_epoch, rtf ]
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.millis_since_epoch: [ 1671033474411 ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ "2022-12-14" ] }
|
||||
- match: { hits.hits.1.fields.millis_since_epoch: [ -1 ] }
|
||||
- is_false: hits.hits.1.fields.rtf
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ millis_since_epoch, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ millis_since_epoch ]
|
||||
sort: rtf
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.millis_since_epoch: [ 1671033474411 ] }
|
||||
- match: { hits.hits.1.fields.millis_since_epoch: [ -1 ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ millis_since_epoch ]
|
||||
sort: rtf_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
range:
|
||||
rtf_search:
|
||||
gte: "2022-12-14"
|
||||
fields: [ millis_since_epoch, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: date
|
||||
format: yyyy-MM-dd
|
||||
script: |
|
||||
if(doc['millis_since_epoch'].value < 0) throw new Exception("date before 1970");
|
||||
emit(doc['millis_since_epoch'].value);
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.millis_since_epoch: [ 1671033474411 ] }
|
||||
- match: { hits.hits.0.fields.rtf_search: [ "2022-12-14" ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
range:
|
||||
rtf_search:
|
||||
gte: "2022-12-14"
|
||||
fields: [ millis_since_epoch, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: date
|
||||
format: yyyy-MM-dd
|
||||
script: |
|
||||
if(doc['millis_since_epoch'].value < 0) throw new Exception("date before 1970");
|
||||
emit(doc['millis_since_epoch'].value);
|
||||
on_script_error: fail
|
|
@ -0,0 +1,177 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: ip
|
||||
script: |
|
||||
if(doc['ip_string'].value.length() <= 0) throw new Exception("empty");
|
||||
emit(doc['ip_string'].value);
|
||||
on_script_error: continue
|
||||
rtf_strict_error:
|
||||
type: ip
|
||||
script: |
|
||||
if(doc['ip_string'].value.length() <= 0) throw new Exception("empty");
|
||||
emit(doc['ip_string'].value);
|
||||
on_script_error: fail
|
||||
properties:
|
||||
ip_string:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"ip_string": "192.68.0.1"}
|
||||
{"index":{}}
|
||||
{"ip_string": ""}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
term:
|
||||
rtf:
|
||||
192.68.0.1
|
||||
fields: [ ip_string, rtf ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.ip_string: [ "192.68.0.1" ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ 192.68.0.1 ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
term:
|
||||
rtf_strict_error: 192.68.0.1
|
||||
fields: [ ip_string, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
rtf:
|
||||
terms:
|
||||
field: rtf
|
||||
- length: { aggregations.rtf.buckets: 1 }
|
||||
- match: { aggregations.rtf.buckets.0.key: 192.68.0.1 }
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
rtf:
|
||||
terms:
|
||||
field: rtf_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ ip_string, rtf ]
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.ip_string: [ "192.68.0.1" ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ "192.68.0.1" ] }
|
||||
- match: { hits.hits.1.fields.ip_string: [ "" ] }
|
||||
- is_false: hits.hits.1.fields.rtf
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ ip_string, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ ip_string ]
|
||||
sort: rtf
|
||||
- match: { hits.total.value: 2 }
|
||||
- match: { hits.hits.0.fields.ip_string: [ "192.68.0.1" ] }
|
||||
- match: { hits.hits.1.fields.ip_string: [ "" ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ ip_string ]
|
||||
sort: rtf_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: "192.68.0.1"
|
||||
fields: [ ip_string, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: ip
|
||||
script: |
|
||||
if(doc['ip_string'].value.length() <= 0) throw new Exception("empty");
|
||||
emit(doc['ip_string'].value);
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.ip_string: [ "192.68.0.1" ] }
|
||||
- match: { hits.hits.0.fields.rtf_search: [ "192.68.0.1" ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: "192.68.0.1"
|
||||
fields: [ ip_string, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: ip
|
||||
script: |
|
||||
if(doc['ip_string'].value.length() <= 0) throw new Exception("empty");
|
||||
emit(doc['ip_string'].value);
|
||||
on_script_error: fail
|
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
setup:
|
||||
- do:
|
||||
indices.create:
|
||||
index: testindex
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
mappings:
|
||||
runtime:
|
||||
rtf:
|
||||
type: boolean
|
||||
script: |
|
||||
if(doc['age'].value < 0) throw new Exception("invalid age");
|
||||
emit(doc['age'].value >= 18);
|
||||
on_script_error: continue
|
||||
rtf_strict_error:
|
||||
type: boolean
|
||||
script: |
|
||||
if(doc['age'].value <= 0) throw new Exception("invalid age");
|
||||
emit(doc['age'].value >=18);
|
||||
on_script_error: fail
|
||||
properties:
|
||||
age:
|
||||
type: integer
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
index: testindex
|
||||
refresh: true
|
||||
body: |
|
||||
{"index":{}}
|
||||
{"age": 14}
|
||||
{"index":{}}
|
||||
{"age": 20}
|
||||
{"index":{}}
|
||||
{"age": -1}
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf:
|
||||
true
|
||||
fields: [ age, rtf ]
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.age: [ 20 ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ true ] }
|
||||
|
||||
---
|
||||
"Query rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_strict_error: true
|
||||
fields: [ age, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Aggregate on rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
rtf:
|
||||
terms:
|
||||
field: rtf
|
||||
order: { "_key": "asc" }
|
||||
- length: { aggregations.rtf.buckets: 2 }
|
||||
- match: { aggregations.rtf.buckets.0.key_as_string: "false" }
|
||||
- match: { aggregations.rtf.buckets.1.key_as_string: "true" }
|
||||
---
|
||||
"Aggregate on rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
aggs:
|
||||
rtf:
|
||||
terms:
|
||||
field: rtf_strict_error
|
||||
|
||||
---
|
||||
"Fields retrieval with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ age, rtf ]
|
||||
sort: { "age": "desc" }
|
||||
- match: { hits.total.value: 3 }
|
||||
- match: { hits.hits.0.fields.age: [ 20 ] }
|
||||
- match: { hits.hits.0.fields.rtf: [ true ] }
|
||||
- match: { hits.hits.1.fields.age: [ 14 ] }
|
||||
- match: { hits.hits.1.fields.rtf: [ false ] }
|
||||
- match: { hits.hits.2.fields.age: [ -1 ] }
|
||||
- is_false: hits.hits.2.fields.rtf
|
||||
|
||||
---
|
||||
"Fields retrieval with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ age, rtf_strict_error ]
|
||||
|
||||
---
|
||||
"Sorting with ignoring error":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ age ]
|
||||
sort: rtf
|
||||
- match: { hits.total.value: 3 }
|
||||
- match: { hits.hits.0.fields.age: [ 14 ] }
|
||||
- match: { hits.hits.1.fields.age: [ 20 ] }
|
||||
- match: { hits.hits.2.fields.age: [ -1 ] }
|
||||
|
||||
---
|
||||
"Sorting with with failing on error":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query: { match_all: { } }
|
||||
fields: [ age ]
|
||||
sort: rtf_strict_error
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error continue":
|
||||
- do:
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: true
|
||||
fields: [ age, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: boolean
|
||||
script: |
|
||||
if(doc['age'].value < 0) throw new Exception("invalid age");
|
||||
emit(doc['age'].value >= 18);
|
||||
on_script_error: continue
|
||||
|
||||
- match: { hits.total.value: 1 }
|
||||
- match: { hits.hits.0.fields.age: [ 20 ] }
|
||||
- match: { hits.hits.0.fields.rtf_search: [ true ] }
|
||||
|
||||
---
|
||||
"Query search time rtf with on_script_error fail":
|
||||
- do:
|
||||
catch: /type=script_exception, reason=runtime error/
|
||||
search:
|
||||
index: testindex
|
||||
body:
|
||||
query:
|
||||
match:
|
||||
rtf_search: true
|
||||
fields: [ age, rtf_search ]
|
||||
runtime_mappings:
|
||||
rtf_search:
|
||||
type: boolean
|
||||
script: |
|
||||
if(doc['age'].value < 0) throw new Exception("invalid age");
|
||||
emit(doc['age'].value >= 18);
|
||||
on_script_error: fail
|
|
@ -215,7 +215,7 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
abstract static class Builder<Factory> extends RuntimeField.Builder {
|
||||
private final ScriptContext<Factory> scriptContext;
|
||||
|
||||
final FieldMapper.Parameter<Script> script = new FieldMapper.Parameter<>(
|
||||
private final FieldMapper.Parameter<Script> script = new FieldMapper.Parameter<>(
|
||||
"script",
|
||||
true,
|
||||
() -> null,
|
||||
|
@ -225,6 +225,8 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
Objects::toString
|
||||
).setSerializerCheck((id, ic, v) -> ic);
|
||||
|
||||
private final FieldMapper.Parameter<String> onScriptError = FieldMapper.Parameter.onScriptErrorParam(m -> m.onScriptError, script);
|
||||
|
||||
Builder(String name, ScriptContext<Factory> scriptContext) {
|
||||
super(name);
|
||||
this.scriptContext = scriptContext;
|
||||
|
@ -247,7 +249,8 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
protected final RuntimeField createChildRuntimeField(
|
||||
MappingParserContext parserContext,
|
||||
String parent,
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
if (script.isConfigured()) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -257,7 +260,7 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
String fullName = parent + "." + name;
|
||||
return new LeafRuntimeField(
|
||||
name,
|
||||
createFieldType(fullName, getCompositeLeafFactory(parentScriptFactory), getScript(), meta()),
|
||||
createFieldType(fullName, getCompositeLeafFactory(parentScriptFactory), getScript(), meta(), onScriptError),
|
||||
getParameters()
|
||||
);
|
||||
}
|
||||
|
@ -267,26 +270,41 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
}
|
||||
|
||||
final RuntimeField createRuntimeField(Factory scriptFactory, Version indexVersion) {
|
||||
var fieldType = createFieldType(name, scriptFactory, getScript(), meta(), indexVersion);
|
||||
var fieldType = createFieldType(
|
||||
name,
|
||||
scriptFactory,
|
||||
getScript(),
|
||||
meta(),
|
||||
indexVersion,
|
||||
OnScriptError.fromString(onScriptError.get())
|
||||
);
|
||||
return new LeafRuntimeField(name, fieldType, getParameters());
|
||||
}
|
||||
|
||||
abstract AbstractScriptFieldType<?> createFieldType(String name, Factory factory, Script script, Map<String, String> meta);
|
||||
abstract AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
);
|
||||
|
||||
AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
Version supportedVersion
|
||||
Version supportedVersion,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return createFieldType(name, factory, script, meta);
|
||||
return createFieldType(name, factory, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<FieldMapper.Parameter<?>> getParameters() {
|
||||
List<FieldMapper.Parameter<?>> parameters = new ArrayList<>(super.getParameters());
|
||||
parameters.add(script);
|
||||
parameters.add(onScriptError);
|
||||
return Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
|
@ -296,5 +314,6 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
|
|||
}
|
||||
return script.get();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ public class BooleanFieldMapper extends FieldMapper {
|
|||
BooleanFieldScript.Factory scriptFactory = scriptCompiler.compile(script.get(), BooleanFieldScript.CONTEXT);
|
||||
return scriptFactory == null
|
||||
? null
|
||||
: (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(name, script.get().getParams(), lookup)
|
||||
: (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(name, script.get().getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer);
|
||||
}
|
||||
|
|
|
@ -46,9 +46,10 @@ public final class BooleanScriptFieldType extends AbstractScriptFieldType<Boolea
|
|||
String name,
|
||||
BooleanFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new BooleanScriptFieldType(name, factory, script, meta);
|
||||
return new BooleanScriptFieldType(name, factory, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,10 +68,16 @@ public final class BooleanScriptFieldType extends AbstractScriptFieldType<Boolea
|
|||
return new Builder(name).createRuntimeField(BooleanFieldScript.PARSE_FROM_SOURCE);
|
||||
}
|
||||
|
||||
BooleanScriptFieldType(String name, BooleanFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
BooleanScriptFieldType(
|
||||
String name,
|
||||
BooleanFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -47,6 +47,8 @@ public class CompositeRuntimeField implements RuntimeField {
|
|||
}
|
||||
});
|
||||
|
||||
private final FieldMapper.Parameter<String> onScriptError = FieldMapper.Parameter.onScriptErrorParam(m -> m.onScriptError, script);
|
||||
|
||||
private final FieldMapper.Parameter<Map<String, Object>> fields = new FieldMapper.Parameter<Map<String, Object>>(
|
||||
"fields",
|
||||
false,
|
||||
|
@ -66,6 +68,7 @@ public class CompositeRuntimeField implements RuntimeField {
|
|||
List<FieldMapper.Parameter<?>> parameters = new ArrayList<>(super.getParameters());
|
||||
parameters.add(script);
|
||||
parameters.add(fields);
|
||||
parameters.add(onScriptError);
|
||||
return Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
|
@ -73,7 +76,8 @@ public class CompositeRuntimeField implements RuntimeField {
|
|||
protected RuntimeField createChildRuntimeField(
|
||||
MappingParserContext parserContext,
|
||||
String parent,
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
throw new IllegalArgumentException("Composite field [" + name + "] cannot be a child of composite field [" + parent + "]");
|
||||
}
|
||||
|
@ -81,11 +85,15 @@ public class CompositeRuntimeField implements RuntimeField {
|
|||
@Override
|
||||
protected RuntimeField createRuntimeField(MappingParserContext parserContext) {
|
||||
CompositeFieldScript.Factory factory = parserContext.scriptCompiler().compile(script.get(), CompositeFieldScript.CONTEXT);
|
||||
Function<RuntimeField.Builder, RuntimeField> builder = b -> b.createChildRuntimeField(
|
||||
parserContext,
|
||||
name,
|
||||
lookup -> factory.newFactory(name, script.get().getParams(), lookup)
|
||||
);
|
||||
Function<RuntimeField.Builder, RuntimeField> builder = b -> {
|
||||
OnScriptError onScriptError = OnScriptError.fromString(this.onScriptError.get());
|
||||
return b.createChildRuntimeField(
|
||||
parserContext,
|
||||
name,
|
||||
lookup -> factory.newFactory(name, script.get().getParams(), lookup, onScriptError),
|
||||
onScriptError
|
||||
);
|
||||
};
|
||||
Map<String, RuntimeField> runtimeFields = RuntimeField.parseRuntimeFields(
|
||||
new HashMap<>(fields.getValue()),
|
||||
parserContext,
|
||||
|
|
|
@ -303,9 +303,13 @@ public final class DateFieldMapper extends FieldMapper {
|
|||
DateFieldScript.Factory factory = scriptCompiler.compile(script.get(), DateFieldScript.CONTEXT);
|
||||
return factory == null
|
||||
? null
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(name, script.get().getParams(), lookup, buildFormatter())
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer::accept);
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(
|
||||
name,
|
||||
script.get().getParams(),
|
||||
lookup,
|
||||
buildFormatter(),
|
||||
OnScriptError.FAIL
|
||||
).newInstance(ctx).runForDoc(doc, consumer::accept);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -87,23 +87,29 @@ public class DateScriptFieldType extends AbstractScriptFieldType<DateFieldScript
|
|||
return Collections.unmodifiableList(parameters);
|
||||
}
|
||||
|
||||
AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
DateFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
Version supportedVersion,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
String pattern = format.getValue() == null ? DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern() : format.getValue();
|
||||
Locale locale = this.locale.getValue() == null ? Locale.ROOT : this.locale.getValue();
|
||||
DateFormatter dateTimeFormatter = DateFormatter.forPattern(pattern, supportedVersion).withLocale(locale);
|
||||
return new DateScriptFieldType(name, factory, dateTimeFormatter, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
DateFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
Version supportedVersion
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
String pattern = format.getValue() == null ? DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.pattern() : format.getValue();
|
||||
Locale locale = this.locale.getValue() == null ? Locale.ROOT : this.locale.getValue();
|
||||
DateFormatter dateTimeFormatter = DateFormatter.forPattern(pattern, supportedVersion).withLocale(locale);
|
||||
return new DateScriptFieldType(name, factory, dateTimeFormatter, script, meta);
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractScriptFieldType<?> createFieldType(String name, DateFieldScript.Factory factory, Script script, Map<String, String> meta) {
|
||||
return createFieldType(name, factory, script, meta, Version.CURRENT);
|
||||
return createFieldType(name, factory, script, meta, Version.CURRENT, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,11 +137,12 @@ public class DateScriptFieldType extends AbstractScriptFieldType<DateFieldScript
|
|||
DateFieldScript.Factory scriptFactory,
|
||||
DateFormatter dateTimeFormatter,
|
||||
Script script,
|
||||
Map<String, String> meta
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, dateTimeFormatter),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, dateTimeFormatter, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -47,9 +47,10 @@ public final class DoubleScriptFieldType extends AbstractScriptFieldType<DoubleF
|
|||
String name,
|
||||
DoubleFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new DoubleScriptFieldType(name, factory, script, meta);
|
||||
return new DoubleScriptFieldType(name, factory, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,10 +68,16 @@ public final class DoubleScriptFieldType extends AbstractScriptFieldType<DoubleF
|
|||
return new Builder(name).createRuntimeField(DoubleFieldScript.PARSE_FROM_SOURCE);
|
||||
}
|
||||
|
||||
DoubleScriptFieldType(String name, DoubleFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
DoubleScriptFieldType(
|
||||
String name,
|
||||
DoubleFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -143,7 +143,7 @@ public class GeoPointFieldMapper extends AbstractPointGeometryFieldMapper<GeoPoi
|
|||
GeoPointFieldScript.Factory factory = scriptCompiler.compile(this.script.get(), GeoPointFieldScript.CONTEXT);
|
||||
return factory == null
|
||||
? null
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(name, script.get().getParams(), lookup)
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(name, script.get().getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer);
|
||||
}
|
||||
|
|
|
@ -50,9 +50,10 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType<GeoPo
|
|||
String name,
|
||||
GeoPointFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new GeoPointScriptFieldType(name, factory, getScript(), meta());
|
||||
return new GeoPointScriptFieldType(name, factory, getScript(), meta(), onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,10 +67,16 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType<GeoPo
|
|||
}
|
||||
});
|
||||
|
||||
GeoPointScriptFieldType(String name, GeoPointFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
GeoPointScriptFieldType(
|
||||
String name,
|
||||
GeoPointFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
@ -154,7 +161,7 @@ public final class GeoPointScriptFieldType extends AbstractScriptFieldType<GeoPo
|
|||
) {
|
||||
return ctx -> {
|
||||
GeoPointFieldScript script = delegateLeafFactory.apply(ctx);
|
||||
return new AbstractLongFieldScript(name, Map.of(), lookup, ctx) {
|
||||
return new AbstractLongFieldScript(name, Map.of(), lookup, OnScriptError.FAIL, ctx) {
|
||||
private int docId;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -145,7 +145,7 @@ public class IpFieldMapper extends FieldMapper {
|
|||
IpFieldScript.Factory factory = scriptCompiler.compile(this.script.get(), IpFieldScript.CONTEXT);
|
||||
return factory == null
|
||||
? null
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(name, script.get().getParams(), lookup)
|
||||
: (lookup, ctx, doc, consumer) -> factory.newFactory(name, script.get().getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer);
|
||||
}
|
||||
|
|
|
@ -45,8 +45,14 @@ public final class IpScriptFieldType extends AbstractScriptFieldType<IpFieldScri
|
|||
|
||||
public static final RuntimeField.Parser PARSER = new RuntimeField.Parser(name -> new Builder<>(name, IpFieldScript.CONTEXT) {
|
||||
@Override
|
||||
AbstractScriptFieldType<?> createFieldType(String name, IpFieldScript.Factory factory, Script script, Map<String, String> meta) {
|
||||
return new IpScriptFieldType(name, factory, getScript(), meta());
|
||||
AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
IpFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new IpScriptFieldType(name, factory, getScript(), meta(), onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,10 +66,16 @@ public final class IpScriptFieldType extends AbstractScriptFieldType<IpFieldScri
|
|||
}
|
||||
});
|
||||
|
||||
IpScriptFieldType(String name, IpFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
IpScriptFieldType(
|
||||
String name,
|
||||
IpFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -245,7 +245,7 @@ public final class KeywordFieldMapper extends FieldMapper {
|
|||
StringFieldScript.Factory scriptFactory = scriptCompiler.compile(script.get(), StringFieldScript.CONTEXT);
|
||||
return scriptFactory == null
|
||||
? null
|
||||
: (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(name, script.get().getParams(), lookup)
|
||||
: (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(name, script.get().getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer);
|
||||
}
|
||||
|
|
|
@ -54,9 +54,10 @@ public final class KeywordScriptFieldType extends AbstractScriptFieldType<String
|
|||
String name,
|
||||
StringFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new KeywordScriptFieldType(name, factory, script, meta);
|
||||
return new KeywordScriptFieldType(name, factory, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,10 +75,16 @@ public final class KeywordScriptFieldType extends AbstractScriptFieldType<String
|
|||
return new Builder(name).createRuntimeField(StringFieldScript.PARSE_FROM_SOURCE);
|
||||
}
|
||||
|
||||
public KeywordScriptFieldType(String name, StringFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
public KeywordScriptFieldType(
|
||||
String name,
|
||||
StringFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -43,8 +43,14 @@ public final class LongScriptFieldType extends AbstractScriptFieldType<LongField
|
|||
}
|
||||
|
||||
@Override
|
||||
AbstractScriptFieldType<?> createFieldType(String name, LongFieldScript.Factory factory, Script script, Map<String, String> meta) {
|
||||
return new LongScriptFieldType(name, factory, script, meta);
|
||||
AbstractScriptFieldType<?> createFieldType(
|
||||
String name,
|
||||
LongFieldScript.Factory factory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new LongScriptFieldType(name, factory, script, meta, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,10 +68,16 @@ public final class LongScriptFieldType extends AbstractScriptFieldType<LongField
|
|||
return new Builder(name).createRuntimeField(LongFieldScript.PARSE_FROM_SOURCE);
|
||||
}
|
||||
|
||||
public LongScriptFieldType(String name, LongFieldScript.Factory scriptFactory, Script script, Map<String, String> meta) {
|
||||
public LongScriptFieldType(
|
||||
String name,
|
||||
LongFieldScript.Factory scriptFactory,
|
||||
Script script,
|
||||
Map<String, String> meta,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(
|
||||
name,
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup),
|
||||
searchLookup -> scriptFactory.newFactory(name, script.getParams(), searchLookup, onScriptError),
|
||||
script,
|
||||
scriptFactory.isResultDeterministic(),
|
||||
meta
|
||||
|
|
|
@ -159,7 +159,8 @@ public final class LookupRuntimeFieldType extends MappedFieldType {
|
|||
protected RuntimeField createChildRuntimeField(
|
||||
MappingParserContext parserContext,
|
||||
String parentName,
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return createRuntimeField(parserContext);
|
||||
}
|
||||
|
|
|
@ -592,7 +592,7 @@ public class NumberFieldMapper extends FieldMapper {
|
|||
@Override
|
||||
public FieldValues<Number> compile(String fieldName, Script script, ScriptCompiler compiler) {
|
||||
DoubleFieldScript.Factory scriptFactory = compiler.compile(script, DoubleFieldScript.CONTEXT);
|
||||
return (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(fieldName, script.getParams(), lookup)
|
||||
return (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(fieldName, script.getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer::accept);
|
||||
}
|
||||
|
@ -1055,7 +1055,7 @@ public class NumberFieldMapper extends FieldMapper {
|
|||
@Override
|
||||
public FieldValues<Number> compile(String fieldName, Script script, ScriptCompiler compiler) {
|
||||
final LongFieldScript.Factory scriptFactory = compiler.compile(script, LongFieldScript.CONTEXT);
|
||||
return (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(fieldName, script.getParams(), lookup)
|
||||
return (lookup, ctx, doc, consumer) -> scriptFactory.newFactory(fieldName, script.getParams(), lookup, OnScriptError.FAIL)
|
||||
.newInstance(ctx)
|
||||
.runForDoc(doc, consumer::accept);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents the behaviour when a runtime field or an index-time script fails: either fail and raise the error,
|
||||
* or continue and ignore the error.
|
||||
*/
|
||||
public enum OnScriptError {
|
||||
FAIL,
|
||||
CONTINUE;
|
||||
|
||||
/**
|
||||
* Parses the on_script_error parameter from a string into its corresponding enum instance
|
||||
*/
|
||||
public static OnScriptError fromString(final String str) {
|
||||
Objects.requireNonNull(str, "input string is null");
|
||||
return switch (str.toLowerCase(Locale.ROOT)) {
|
||||
case "fail" -> FAIL;
|
||||
case "continue" -> CONTINUE;
|
||||
default -> throw new IllegalArgumentException("Unknown onScriptError [" + str + "]");
|
||||
};
|
||||
}
|
||||
}
|
|
@ -63,7 +63,8 @@ public interface RuntimeField extends ToXContentFragment {
|
|||
protected abstract RuntimeField createChildRuntimeField(
|
||||
MappingParserContext parserContext,
|
||||
String parentName,
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory,
|
||||
OnScriptError onScriptError
|
||||
);
|
||||
|
||||
public final void parse(String name, MappingParserContext parserContext, Map<String, Object> fieldNode) {
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.search.lookup.SourceLookup;
|
||||
|
||||
|
@ -69,10 +70,16 @@ public abstract class AbstractFieldScript extends DocBasedScript {
|
|||
protected final String fieldName;
|
||||
protected final SourceLookup sourceLookup;
|
||||
private final Map<String, Object> params;
|
||||
private final OnScriptError onScriptError;
|
||||
|
||||
public AbstractFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
public AbstractFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
LeafReaderContext ctx,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
super(new DocValuesDocReader(searchLookup, ctx));
|
||||
|
||||
this.fieldName = fieldName;
|
||||
Map<String, Object> docAsMap = docAsMap();
|
||||
this.sourceLookup = (SourceLookup) docAsMap.get("_source");
|
||||
|
@ -80,6 +87,7 @@ public abstract class AbstractFieldScript extends DocBasedScript {
|
|||
params.put("_source", sourceLookup);
|
||||
params.put("_fields", docAsMap.get("_fields"));
|
||||
this.params = new DynamicMap(params, PARAMS_FUNCTIONS);
|
||||
this.onScriptError = onScriptError;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +149,15 @@ public abstract class AbstractFieldScript extends DocBasedScript {
|
|||
public final void runForDoc(int docId) {
|
||||
prepareExecute();
|
||||
setDocument(docId);
|
||||
execute();
|
||||
try {
|
||||
execute();
|
||||
} catch (Exception e) {
|
||||
if (onScriptError == OnScriptError.CONTINUE) {
|
||||
// ignore
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -22,8 +23,14 @@ public abstract class AbstractLongFieldScript extends AbstractFieldScript {
|
|||
private long[] values = new long[1];
|
||||
private int count;
|
||||
|
||||
public AbstractLongFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public AbstractLongFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.core.Booleans;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -22,8 +23,8 @@ public abstract class BooleanFieldScript extends AbstractFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new BooleanFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new BooleanFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -38,11 +39,11 @@ public abstract class BooleanFieldScript extends AbstractFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new BooleanFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new BooleanFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -61,7 +62,7 @@ public abstract class BooleanFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -71,8 +72,14 @@ public abstract class BooleanFieldScript extends AbstractFieldScript {
|
|||
private int trues;
|
||||
private int falses;
|
||||
|
||||
public BooleanFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public BooleanFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package org.elasticsearch.script;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -27,7 +28,12 @@ public abstract class CompositeFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
CompositeFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
CompositeFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -36,8 +42,14 @@ public abstract class CompositeFieldScript extends AbstractFieldScript {
|
|||
|
||||
private final Map<String, List<Object>> fieldValues = new HashMap<>();
|
||||
|
||||
public CompositeFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public CompositeFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.common.time.DateFormatter;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -21,8 +22,14 @@ public abstract class DateFieldScript extends AbstractLongFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, DateFormatter formatter) {
|
||||
return ctx -> new DateFieldScript(field, params, lookup, formatter, ctx) {
|
||||
public LeafFactory newFactory(
|
||||
String field,
|
||||
Map<String, Object> params,
|
||||
SearchLookup lookup,
|
||||
DateFormatter formatter,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return ctx -> new DateFieldScript(field, params, lookup, formatter, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -37,11 +44,11 @@ public abstract class DateFieldScript extends AbstractLongFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup, formatter) -> {
|
||||
return (leafFieldName, params, searchLookup, formatter, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new DateFieldScript(leafFieldName, params, searchLookup, formatter, ctx) {
|
||||
return new DateFieldScript(leafFieldName, params, searchLookup, formatter, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -60,7 +67,13 @@ public abstract class DateFieldScript extends AbstractLongFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter);
|
||||
LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
DateFormatter formatter,
|
||||
OnScriptError onScriptError
|
||||
);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -74,9 +87,10 @@ public abstract class DateFieldScript extends AbstractLongFieldScript {
|
|||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
DateFormatter formatter,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
super(fieldName, params, searchLookup, onScriptError, ctx);
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -21,8 +22,8 @@ public abstract class DoubleFieldScript extends AbstractFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new DoubleFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new DoubleFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -37,11 +38,11 @@ public abstract class DoubleFieldScript extends AbstractFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new DoubleFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new DoubleFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -60,7 +61,7 @@ public abstract class DoubleFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -70,8 +71,14 @@ public abstract class DoubleFieldScript extends AbstractFieldScript {
|
|||
private double[] values = new double[1];
|
||||
private int count;
|
||||
|
||||
public DoubleFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public DoubleFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.apache.lucene.util.ArrayUtil;
|
|||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.GeoUtils;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Collections;
|
||||
|
@ -31,8 +32,8 @@ public abstract class GeoPointFieldScript extends AbstractFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new GeoPointFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new GeoPointFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -47,11 +48,11 @@ public abstract class GeoPointFieldScript extends AbstractFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new GeoPointFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new GeoPointFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -70,7 +71,7 @@ public abstract class GeoPointFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -81,8 +82,14 @@ public abstract class GeoPointFieldScript extends AbstractFieldScript {
|
|||
private double[] lons = new double[1];
|
||||
private int count;
|
||||
|
||||
public GeoPointFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public GeoPointFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.apache.lucene.util.ArrayUtil;
|
|||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.network.InetAddresses;
|
||||
import org.elasticsearch.index.mapper.IpFieldMapper;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
|
@ -42,8 +43,8 @@ public abstract class IpFieldScript extends AbstractFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new IpFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new IpFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -58,11 +59,11 @@ public abstract class IpFieldScript extends AbstractFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new IpFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new IpFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -81,7 +82,7 @@ public abstract class IpFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -91,8 +92,14 @@ public abstract class IpFieldScript extends AbstractFieldScript {
|
|||
private BytesRef[] values = new BytesRef[1];
|
||||
private int count;
|
||||
|
||||
public IpFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public IpFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -20,8 +21,8 @@ public abstract class LongFieldScript extends AbstractLongFieldScript {
|
|||
|
||||
public static final Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new LongFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new LongFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -36,11 +37,11 @@ public abstract class LongFieldScript extends AbstractLongFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new LongFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new LongFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -59,15 +60,21 @@ public abstract class LongFieldScript extends AbstractLongFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
LongFieldScript newInstance(LeafReaderContext ctx);
|
||||
}
|
||||
|
||||
public LongFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public LongFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, onScriptError, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ package org.elasticsearch.script;
|
|||
|
||||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.script.field.LongDocValuesField;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
|
@ -21,7 +22,7 @@ public class SortedNumericDocValuesLongFieldScript extends AbstractLongFieldScri
|
|||
final LongDocValuesField longDocValuesField;
|
||||
|
||||
public SortedNumericDocValuesLongFieldScript(String fieldName, SearchLookup lookup, LeafReaderContext ctx) {
|
||||
super(fieldName, Map.of(), lookup, ctx);
|
||||
super(fieldName, Map.of(), lookup, OnScriptError.FAIL, ctx);
|
||||
try {
|
||||
longDocValuesField = new LongDocValuesField(DocValues.getSortedNumeric(ctx.reader(), fieldName), fieldName);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -23,7 +24,7 @@ public class SortedSetDocValuesStringFieldScript extends StringFieldScript {
|
|||
boolean hasValue = false;
|
||||
|
||||
public SortedSetDocValuesStringFieldScript(String fieldName, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, Map.of(), searchLookup, ctx);
|
||||
super(fieldName, Map.of(), searchLookup, OnScriptError.FAIL, ctx);
|
||||
try {
|
||||
sortedSetDocValues = DocValues.getSortedSet(ctx.reader(), fieldName);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package org.elasticsearch.script;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -28,8 +29,8 @@ public abstract class StringFieldScript extends AbstractFieldScript {
|
|||
|
||||
public static final StringFieldScript.Factory PARSE_FROM_SOURCE = new Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup) {
|
||||
return ctx -> new StringFieldScript(field, params, lookup, ctx) {
|
||||
public LeafFactory newFactory(String field, Map<String, Object> params, SearchLookup lookup, OnScriptError onScriptError) {
|
||||
return ctx -> new StringFieldScript(field, params, lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emitFromSource();
|
||||
|
@ -44,11 +45,11 @@ public abstract class StringFieldScript extends AbstractFieldScript {
|
|||
};
|
||||
|
||||
public static Factory leafAdapter(Function<SearchLookup, CompositeFieldScript.LeafFactory> parentFactory) {
|
||||
return (leafFieldName, params, searchLookup) -> {
|
||||
return (leafFieldName, params, searchLookup, onScriptError) -> {
|
||||
CompositeFieldScript.LeafFactory parentLeafFactory = parentFactory.apply(searchLookup);
|
||||
return (LeafFactory) ctx -> {
|
||||
CompositeFieldScript compositeFieldScript = parentLeafFactory.newInstance(ctx);
|
||||
return new StringFieldScript(leafFieldName, params, searchLookup, ctx) {
|
||||
return new StringFieldScript(leafFieldName, params, searchLookup, onScriptError, ctx) {
|
||||
@Override
|
||||
public void setDocument(int docId) {
|
||||
compositeFieldScript.setDocument(docId);
|
||||
|
@ -67,7 +68,7 @@ public abstract class StringFieldScript extends AbstractFieldScript {
|
|||
public static final String[] PARAMETERS = {};
|
||||
|
||||
public interface Factory extends ScriptFactory {
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup);
|
||||
LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup, OnScriptError onScriptError);
|
||||
}
|
||||
|
||||
public interface LeafFactory {
|
||||
|
@ -77,8 +78,14 @@ public abstract class StringFieldScript extends AbstractFieldScript {
|
|||
private final List<String> results = new ArrayList<>();
|
||||
private long chars;
|
||||
|
||||
public StringFieldScript(String fieldName, Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
public StringFieldScript(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError,
|
||||
LeafReaderContext ctx
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx, onScriptError);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.time.DateUtils;
|
||||
import org.elasticsearch.index.mapper.MapperServiceTestCase;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptContext;
|
||||
import org.elasticsearch.script.StringFieldScript;
|
||||
|
@ -264,7 +265,12 @@ public class TimeSeriesModeTests extends MapperServiceTestCase {
|
|||
if (context.equals(StringFieldScript.CONTEXT) && script.getLang().equals("mock")) {
|
||||
return (T) new StringFieldScript.Factory() {
|
||||
@Override
|
||||
public LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
throw new UnsupportedOperationException("error should be thrown before getting here");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,9 +8,14 @@
|
|||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.tests.index.RandomIndexWriter;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
|
@ -18,6 +23,7 @@ import org.elasticsearch.common.geo.ShapeRelation;
|
|||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.index.fielddata.FieldDataContext;
|
||||
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
||||
import org.elasticsearch.index.query.ExistsQueryBuilder;
|
||||
import org.elasticsearch.index.query.SearchExecutionContext;
|
||||
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
|
||||
import org.elasticsearch.script.BooleanFieldScript;
|
||||
|
@ -38,7 +44,9 @@ import org.elasticsearch.xcontent.json.JsonXContent;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -157,6 +165,45 @@ public abstract class AbstractScriptFieldTypeTestCase extends MapperServiceTestC
|
|||
assertEquals(concreteIndexType.isAggregatable(), scriptFieldType.isAggregatable());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that running query on a runtime field script that fails has the expected behaviour according to its configuration
|
||||
*/
|
||||
public final void testOnScriptError() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [1]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
{
|
||||
AbstractScriptFieldType<?> fieldType = build("error", Collections.emptyMap(), OnScriptError.CONTINUE);
|
||||
SearchExecutionContext searchExecutionContext = mockContext(true, fieldType);
|
||||
Query query = new ExistsQueryBuilder("test").rewrite(searchExecutionContext).toQuery(searchExecutionContext);
|
||||
assertEquals(0, searcher.count(query));
|
||||
}
|
||||
{
|
||||
AbstractScriptFieldType<?> fieldType = build("error", Collections.emptyMap(), OnScriptError.FAIL);
|
||||
SearchExecutionContext searchExecutionContext = mockContext(true, fieldType);
|
||||
Query query = new ExistsQueryBuilder("test").rewrite(searchExecutionContext).toQuery(searchExecutionContext);
|
||||
expectThrows(RuntimeException.class, () -> searcher.count(query));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void testOnScriptErrorFail() throws IOException {
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [1]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
AbstractScriptFieldType<?> fieldType = build("error", Collections.emptyMap(), OnScriptError.FAIL);
|
||||
SearchExecutionContext searchExecutionContext = mockContext(true, fieldType);
|
||||
Query query = new ExistsQueryBuilder("test").rewrite(searchExecutionContext).toQuery(searchExecutionContext);
|
||||
expectThrows(RuntimeException.class, () -> searcher.count(query));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract AbstractScriptFieldType<?> build(String error, Map<String, Object> emptyMap, OnScriptError onScriptError);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public abstract void testDocValues() throws IOException;
|
||||
|
||||
|
@ -237,6 +284,7 @@ public abstract class AbstractScriptFieldTypeTestCase extends MapperServiceTestC
|
|||
return ft.fielddataBuilder(new FieldDataContext("test", context::lookup, context::sourcePath, fdo))
|
||||
.build(new IndexFieldDataCache.None(), new NoneCircuitBreakerService());
|
||||
});
|
||||
when(context.getMatchingFieldNames(any())).thenReturn(Set.of("dummy_field"));
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,7 +258,13 @@ public class BooleanFieldMapperTests extends MapperTestCase {
|
|||
return new IngestScriptSupport() {
|
||||
@Override
|
||||
protected BooleanFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new BooleanFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {}
|
||||
};
|
||||
|
@ -266,7 +272,13 @@ public class BooleanFieldMapperTests extends MapperTestCase {
|
|||
|
||||
@Override
|
||||
protected BooleanFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new BooleanFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(true);
|
||||
|
|
|
@ -24,10 +24,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class BooleanFieldScriptTests extends FieldScriptTestCase<BooleanFieldScript.Factory> {
|
||||
public static final BooleanFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new BooleanFieldScript(
|
||||
public static final BooleanFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -59,6 +60,7 @@ public class BooleanFieldScriptTests extends FieldScriptTestCase<BooleanFieldScr
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -253,7 +253,10 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
assertThat(searcher.count(simpleMappedFieldType().termQuery(true, mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery("true", mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(false, mockContext())), equalTo(0));
|
||||
assertThat(searcher.count(build("xor_param", Map.of("param", false)).termQuery(true, mockContext())), equalTo(1));
|
||||
assertThat(
|
||||
searcher.count(build("xor_param", Map.of("param", false), OnScriptError.FAIL).termQuery(true, mockContext())),
|
||||
equalTo(1)
|
||||
);
|
||||
}
|
||||
}
|
||||
try (Directory directory = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), directory)) {
|
||||
|
@ -264,7 +267,10 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
assertThat(searcher.count(simpleMappedFieldType().termQuery("false", mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(null, mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(true, mockContext())), equalTo(0));
|
||||
assertThat(searcher.count(build("xor_param", Map.of("param", false)).termQuery(false, mockContext())), equalTo(1));
|
||||
assertThat(
|
||||
searcher.count(build("xor_param", Map.of("param", false), OnScriptError.FAIL).termQuery(false, mockContext())),
|
||||
equalTo(1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -400,12 +406,12 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
|
||||
@Override
|
||||
protected BooleanScriptFieldType simpleMappedFieldType() {
|
||||
return build("read_foo", Map.of());
|
||||
return build("read_foo", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MappedFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -413,13 +419,20 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
return "boolean";
|
||||
}
|
||||
|
||||
private static BooleanScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected BooleanScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new BooleanScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static BooleanFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "read_foo" -> (fieldName, params, lookup) -> (ctx) -> new BooleanFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "read_foo" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -427,7 +440,13 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
}
|
||||
}
|
||||
};
|
||||
case "xor_param" -> (fieldName, params, lookup) -> (ctx) -> new BooleanFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "xor_param" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -435,16 +454,24 @@ public class BooleanScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeT
|
|||
}
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup) -> {
|
||||
case "loop" -> (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, onScriptError) -> ctx -> new BooleanFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static BooleanScriptFieldType build(Script script) {
|
||||
return new BooleanScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ public class BooleanScriptMapperTests extends MapperScriptTestCase<BooleanFieldS
|
|||
private static BooleanFieldScript.Factory factory(Consumer<BooleanFieldScript> executor) {
|
||||
return new BooleanFieldScript.Factory() {
|
||||
@Override
|
||||
public BooleanFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public BooleanFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new BooleanFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public BooleanFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new BooleanFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new BooleanFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -33,10 +33,11 @@ public class CompositeRuntimeFieldTests extends MapperServiceTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
protected <T> T compileScript(Script script, ScriptContext<T> context) {
|
||||
if (context == CompositeFieldScript.CONTEXT) {
|
||||
return (T) (CompositeFieldScript.Factory) (fieldName, params, searchLookup) -> ctx -> new CompositeFieldScript(
|
||||
return (T) (CompositeFieldScript.Factory) (fieldName, params, searchLookup, onScriptError) -> ctx -> new CompositeFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -52,7 +53,13 @@ public class CompositeRuntimeFieldTests extends MapperServiceTestCase {
|
|||
};
|
||||
}
|
||||
if (context == LongFieldScript.CONTEXT) {
|
||||
return (T) (LongFieldScript.Factory) (field, params, lookup) -> ctx -> new LongFieldScript(field, params, lookup, ctx) {
|
||||
return (T) (LongFieldScript.Factory) (field, params, lookup, onScriptError) -> ctx -> new LongFieldScript(
|
||||
field,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
|
||||
|
|
|
@ -669,11 +669,12 @@ public class DateFieldMapperTests extends MapperTestCase {
|
|||
return new IngestScriptSupport() {
|
||||
@Override
|
||||
protected DateFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup, formatter) -> ctx -> new DateFieldScript(
|
||||
return (fieldName, params, searchLookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
formatter,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -683,11 +684,12 @@ public class DateFieldMapperTests extends MapperTestCase {
|
|||
|
||||
@Override
|
||||
protected DateFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup, formatter) -> ctx -> new DateFieldScript(
|
||||
return (fieldName, params, searchLookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
formatter,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -32,11 +32,12 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class DateFieldScriptTests extends FieldScriptTestCase<DateFieldScript.Factory> {
|
||||
public static final DateFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter) -> ctx -> new DateFieldScript(
|
||||
public static final DateFieldScript.Factory DUMMY = (fieldName, params, lookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -69,6 +70,7 @@ public class DateFieldScriptTests extends FieldScriptTestCase<DateFieldScript.Fa
|
|||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
DateFormatter.forPattern(randomDateFormatterPattern()).withLocale(randomLocale(random())),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -104,7 +106,8 @@ public class DateFieldScriptTests extends FieldScriptTestCase<DateFieldScript.Fa
|
|||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
DateFormatter.forPattern("epoch_millis")
|
||||
DateFormatter.forPattern("epoch_millis"),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
DateFieldScript dateFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
List<Long> results = new ArrayList<>();
|
||||
|
|
|
@ -128,7 +128,11 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
|
||||
public void testFormatDuel() throws IOException {
|
||||
DateFormatter formatter = DateFormatter.forPattern(randomDateFormatterPattern()).withLocale(randomLocale(random()));
|
||||
DateScriptFieldType scripted = build(new Script(ScriptType.INLINE, "test", "read_timestamp", Map.of()), formatter);
|
||||
DateScriptFieldType scripted = build(
|
||||
new Script(ScriptType.INLINE, "test", "read_timestamp", Map.of()),
|
||||
formatter,
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
DateFieldMapper.DateFieldType indexed = new DateFieldMapper.DateFieldType("test", formatter);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
long date = randomDate();
|
||||
|
@ -149,7 +153,7 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
List<Long> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
DateScriptFieldType ft = build("add_days", Map.of("days", 1));
|
||||
DateScriptFieldType ft = build("add_days", Map.of("days", 1), OnScriptError.FAIL);
|
||||
DateScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
@Override
|
||||
|
@ -381,7 +385,9 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
assertThat(searcher.count(simpleMappedFieldType().termQuery(1595432181354L, mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(2595432181354L, mockContext())), equalTo(0));
|
||||
assertThat(
|
||||
searcher.count(build("add_days", Map.of("days", 1)).termQuery("2020-07-23T15:36:21.354Z", mockContext())),
|
||||
searcher.count(
|
||||
build("add_days", Map.of("days", 1), OnScriptError.FAIL).termQuery("2020-07-23T15:36:21.354Z", mockContext())
|
||||
),
|
||||
equalTo(1)
|
||||
);
|
||||
checkBadDate(() -> searcher.count(simpleMappedFieldType().termQuery("2020-07-22(-■_■)15:36:21.354Z", mockContext())));
|
||||
|
@ -462,7 +468,11 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
}
|
||||
|
||||
private DateScriptFieldType coolFormattedFieldType() {
|
||||
return build(simpleMappedFieldType().script, DateFormatter.forPattern("yyyy-MM-dd(-■_■)HH:mm:ss.SSSz||epoch_millis"));
|
||||
return build(
|
||||
simpleMappedFieldType().script,
|
||||
DateFormatter.forPattern("yyyy-MM-dd(-■_■)HH:mm:ss.SSSz||epoch_millis"),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -470,21 +480,22 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
return "date";
|
||||
}
|
||||
|
||||
private static DateScriptFieldType build(String code) {
|
||||
return build(code, Map.of());
|
||||
private DateScriptFieldType build(String code) {
|
||||
return build(code, Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
private static DateScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params), DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER);
|
||||
protected DateScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params), DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER, onScriptError);
|
||||
}
|
||||
|
||||
private static DateFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "read_timestamp" -> (fieldName, params, lookup, formatter) -> ctx -> new DateFieldScript(
|
||||
case "read_timestamp" -> (fieldName, params, lookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -495,11 +506,12 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
}
|
||||
}
|
||||
};
|
||||
case "add_days" -> (fieldName, params, lookup, formatter) -> ctx -> new DateFieldScript(
|
||||
case "add_days" -> (fieldName, params, lookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -512,17 +524,30 @@ public class DateScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
}
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup, formatter) -> {
|
||||
case "loop" -> (fieldName, params, lookup, formatter, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
formatter,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static DateScriptFieldType build(Script script, DateFormatter dateTimeFormatter) {
|
||||
return new DateScriptFieldType("test", factory(script), dateTimeFormatter, script, emptyMap());
|
||||
private static DateScriptFieldType build(Script script, DateFormatter dateTimeFormatter, OnScriptError onScriptError) {
|
||||
return new DateScriptFieldType("test", factory(script), dateTimeFormatter, script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static long randomDate() {
|
||||
|
|
|
@ -26,12 +26,13 @@ public class DateScriptMapperTests extends MapperScriptTestCase<DateFieldScript.
|
|||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
DateFormatter formatter
|
||||
DateFormatter formatter,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new DateFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public DateFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new DateFieldScript(fieldName, params, searchLookup, formatter, ctx) {
|
||||
return new DateFieldScript(fieldName, params, searchLookup, formatter, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -2604,7 +2604,8 @@ public class DocumentParserTests extends MapperServiceTestCase {
|
|||
protected RuntimeField createChildRuntimeField(
|
||||
MappingParserContext parserContext,
|
||||
String parentName,
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory
|
||||
Function<SearchLookup, CompositeFieldScript.LeafFactory> parentScriptFactory,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -105,7 +105,13 @@ public class DoubleFieldMapperTests extends NumberFieldMapperTests {
|
|||
|
||||
@Override
|
||||
protected DoubleFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new DoubleFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {}
|
||||
};
|
||||
|
@ -113,7 +119,13 @@ public class DoubleFieldMapperTests extends NumberFieldMapperTests {
|
|||
|
||||
@Override
|
||||
protected DoubleFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new DoubleFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(1.0);
|
||||
|
|
|
@ -31,10 +31,11 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class DoubleFieldScriptTests extends FieldScriptTestCase<DoubleFieldScript.Factory> {
|
||||
public static final DoubleFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new DoubleFieldScript(
|
||||
public static final DoubleFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -66,6 +67,7 @@ public class DoubleFieldScriptTests extends FieldScriptTestCase<DoubleFieldScrip
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -100,7 +102,8 @@ public class DoubleFieldScriptTests extends FieldScriptTestCase<DoubleFieldScrip
|
|||
DoubleFieldScript.LeafFactory leafFactory = fromSource().newFactory(
|
||||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider())
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
DoubleFieldScript doubleFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
List<Double> results = new ArrayList<>();
|
||||
|
|
|
@ -64,7 +64,7 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
List<Double> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
DoubleScriptFieldType ft = build("add_param", Map.of("param", 1));
|
||||
DoubleScriptFieldType ft = build("add_param", Map.of("param", 1), OnScriptError.FAIL);
|
||||
DoubleScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
@Override
|
||||
|
@ -190,7 +190,10 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
assertThat(searcher.count(simpleMappedFieldType().termQuery("1", mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(1, mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(1.1, mockContext())), equalTo(0));
|
||||
assertThat(searcher.count(build("add_param", Map.of("param", 1)).termQuery(2, mockContext())), equalTo(1));
|
||||
assertThat(
|
||||
searcher.count(build("add_param", Map.of("param", 1), OnScriptError.FAIL).termQuery(2, mockContext())),
|
||||
equalTo(1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,12 +226,12 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
|
||||
@Override
|
||||
protected DoubleScriptFieldType simpleMappedFieldType() {
|
||||
return build("read_foo", Map.of());
|
||||
return build("read_foo", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MappedFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -236,13 +239,20 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
return "double";
|
||||
}
|
||||
|
||||
private static DoubleScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected DoubleScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new DoubleScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static DoubleFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "read_foo" -> (fieldName, params, lookup) -> (ctx) -> new DoubleFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "read_foo" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -250,7 +260,13 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
}
|
||||
}
|
||||
};
|
||||
case "add_param" -> (fieldName, params, lookup) -> (ctx) -> new DoubleFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "add_param" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -258,16 +274,24 @@ public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTe
|
|||
}
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup) -> {
|
||||
case "loop" -> (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, onScriptError) -> ctx -> new DoubleFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static DoubleScriptFieldType build(Script script) {
|
||||
return new DoubleScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ public class DoubleScriptMapperTests extends MapperScriptTestCase<DoubleFieldScr
|
|||
private static DoubleFieldScript.Factory factory(Consumer<DoubleFieldScript> executor) {
|
||||
return new DoubleFieldScript.Factory() {
|
||||
@Override
|
||||
public DoubleFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public DoubleFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new DoubleFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public DoubleFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new DoubleFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new DoubleFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -26,10 +26,11 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class GeoPointFieldScriptTests extends FieldScriptTestCase<GeoPointFieldScript.Factory> {
|
||||
public static final GeoPointFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new GeoPointFieldScript(
|
||||
public static final GeoPointFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new GeoPointFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -61,6 +62,7 @@ public class GeoPointFieldScriptTests extends FieldScriptTestCase<GeoPointFieldS
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -64,7 +64,7 @@ public class GeoPointScriptFieldTypeTests extends AbstractNonTextScriptFieldType
|
|||
List<Object> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
GeoPointScriptFieldType ft = build("fromLatLon", Map.of());
|
||||
GeoPointScriptFieldType ft = build("fromLatLon", Map.of(), OnScriptError.FAIL);
|
||||
GeoPointScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
@Override
|
||||
|
@ -213,12 +213,12 @@ public class GeoPointScriptFieldTypeTests extends AbstractNonTextScriptFieldType
|
|||
|
||||
@Override
|
||||
protected GeoPointScriptFieldType simpleMappedFieldType() {
|
||||
return build("fromLatLon", Map.of());
|
||||
return build("fromLatLon", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MappedFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -226,29 +226,44 @@ public class GeoPointScriptFieldTypeTests extends AbstractNonTextScriptFieldType
|
|||
return "geo_point";
|
||||
}
|
||||
|
||||
private static GeoPointScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected GeoPointScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new GeoPointScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static GeoPointFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "fromLatLon" -> (fieldName, params, lookup) -> (ctx) -> new GeoPointFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "fromLatLon" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new GeoPointFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
Map<?, ?> foo = (Map<?, ?>) lookup.source().source().get("foo");
|
||||
emit(((Number) foo.get("lat")).doubleValue(), ((Number) foo.get("lon")).doubleValue());
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup) -> {
|
||||
case "loop" -> (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, onScriptError) -> ctx -> new GeoPointFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static GeoPointScriptFieldType build(Script script) {
|
||||
return new GeoPointScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ public class GeoPointScriptMapperTests extends MapperScriptTestCase<GeoPointFiel
|
|||
private static GeoPointFieldScript.Factory factory(Consumer<GeoPointFieldScript.Emit> executor) {
|
||||
return new GeoPointFieldScript.Factory() {
|
||||
@Override
|
||||
public GeoPointFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public GeoPointFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new GeoPointFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public GeoPointFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new GeoPointFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new GeoPointFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(new Emit(this));
|
||||
|
|
|
@ -128,7 +128,7 @@ public class IndexTimeScriptTests extends MapperServiceTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
protected <T> T compileScript(Script script, ScriptContext<T> context) {
|
||||
if (context.factoryClazz == LongFieldScript.Factory.class) {
|
||||
return (T) (LongFieldScript.Factory) (n, p, l) -> ctx -> new TestLongFieldScript(
|
||||
return (T) (LongFieldScript.Factory) (n, p, l, onScriptError) -> ctx -> new TestLongFieldScript(
|
||||
n,
|
||||
p,
|
||||
l,
|
||||
|
@ -137,7 +137,7 @@ public class IndexTimeScriptTests extends MapperServiceTestCase {
|
|||
);
|
||||
}
|
||||
if (context.factoryClazz == DoubleFieldScript.Factory.class) {
|
||||
return (T) (DoubleFieldScript.Factory) (n, p, l) -> ctx -> new TestDoubleFieldScript(
|
||||
return (T) (DoubleFieldScript.Factory) (n, p, l, onScriptError) -> ctx -> new TestDoubleFieldScript(
|
||||
n,
|
||||
p,
|
||||
l,
|
||||
|
@ -195,7 +195,7 @@ public class IndexTimeScriptTests extends MapperServiceTestCase {
|
|||
LeafReaderContext ctx,
|
||||
Consumer<TestLongFieldScript> executor
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
super(fieldName, params, searchLookup, OnScriptError.FAIL, ctx);
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ public class IndexTimeScriptTests extends MapperServiceTestCase {
|
|||
LeafReaderContext ctx,
|
||||
Consumer<TestDoubleFieldScript> executor
|
||||
) {
|
||||
super(fieldName, params, searchLookup, ctx);
|
||||
super(fieldName, params, searchLookup, OnScriptError.FAIL, ctx);
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
|
|
|
@ -388,7 +388,13 @@ public class IpFieldMapperTests extends MapperTestCase {
|
|||
return new IngestScriptSupport() {
|
||||
@Override
|
||||
protected IpFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new IpFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {}
|
||||
};
|
||||
|
@ -396,7 +402,13 @@ public class IpFieldMapperTests extends MapperTestCase {
|
|||
|
||||
@Override
|
||||
protected IpFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new IpFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("192.168.0.1");
|
||||
|
|
|
@ -32,10 +32,11 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class IpFieldScriptTests extends FieldScriptTestCase<IpFieldScript.Factory> {
|
||||
public static final IpFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new IpFieldScript(
|
||||
public static final IpFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -67,6 +68,7 @@ public class IpFieldScriptTests extends FieldScriptTestCase<IpFieldScript.Factor
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -101,7 +103,8 @@ public class IpFieldScriptTests extends FieldScriptTestCase<IpFieldScript.Factor
|
|||
IpFieldScript.LeafFactory leafFactory = fromSource().newFactory(
|
||||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider())
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
IpFieldScript ipFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
List<InetAddress> results = new ArrayList<>();
|
||||
|
|
|
@ -66,7 +66,7 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
List<Object> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
IpScriptFieldType ft = build("append_param", Map.of("param", ".1"));
|
||||
IpScriptFieldType ft = build("append_param", Map.of("param", ".1"), OnScriptError.FAIL);
|
||||
BinaryScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
DocValueFormat format = ft.docValueFormat(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
|
@ -198,7 +198,7 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [\"200.0.0\"]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
IpScriptFieldType fieldType = build("append_param", Map.of("param", ".1"));
|
||||
IpScriptFieldType fieldType = build("append_param", Map.of("param", ".1"), OnScriptError.FAIL);
|
||||
assertThat(searcher.count(fieldType.termQuery("192.168.0.1", mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(fieldType.termQuery("192.168.0.7", mockContext())), equalTo(0));
|
||||
assertThat(searcher.count(fieldType.termQuery("192.168.0.0/16", mockContext())), equalTo(2));
|
||||
|
@ -240,12 +240,12 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
|
||||
@Override
|
||||
protected IpScriptFieldType simpleMappedFieldType() {
|
||||
return build("read_foo", Map.of());
|
||||
return build("read_foo", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MappedFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -253,13 +253,20 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
return "ip";
|
||||
}
|
||||
|
||||
private static IpScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected IpScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new IpScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static IpFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "read_foo" -> (fieldName, params, lookup) -> (ctx) -> new IpFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "read_foo" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -267,7 +274,13 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
}
|
||||
}
|
||||
};
|
||||
case "append_param" -> (fieldName, params, lookup) -> (ctx) -> new IpFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "append_param" -> (fieldName, params, lookup, onScriptError) -> (ctx) -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -275,16 +288,24 @@ public class IpScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase {
|
|||
}
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup) -> {
|
||||
case "loop" -> (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, onScriptError) -> ctx -> new IpFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static IpScriptFieldType build(Script script) {
|
||||
return new IpScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ public class IpScriptMapperTests extends MapperScriptTestCase<IpFieldScript.Fact
|
|||
private static IpFieldScript.Factory factory(Consumer<IpFieldScript> executor) {
|
||||
return new IpFieldScript.Factory() {
|
||||
@Override
|
||||
public IpFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public IpFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new IpFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public IpFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new IpFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new IpFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -729,7 +729,13 @@ public class KeywordFieldMapperTests extends MapperTestCase {
|
|||
return new IngestScriptSupport() {
|
||||
@Override
|
||||
protected StringFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new StringFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {}
|
||||
};
|
||||
|
@ -737,7 +743,13 @@ public class KeywordFieldMapperTests extends MapperTestCase {
|
|||
|
||||
@Override
|
||||
protected StringFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new StringFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("foo");
|
||||
|
|
|
@ -60,7 +60,7 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
List<String> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
KeywordScriptFieldType ft = build("append_param", Map.of("param", "-suffix"));
|
||||
KeywordScriptFieldType ft = build("append_param", Map.of("param", "-suffix"), OnScriptError.FAIL);
|
||||
StringScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
@Override
|
||||
|
@ -287,7 +287,7 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [2]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-suffix"));
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-suffix"), OnScriptError.FAIL);
|
||||
assertThat(searcher.count(fieldType.termQuery("1-suffix", mockContext())), equalTo(1));
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [2]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-suffix"));
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-suffix"), OnScriptError.FAIL);
|
||||
expectThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
|
@ -375,7 +375,7 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"foo\": [2]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-Suffix"));
|
||||
KeywordScriptFieldType fieldType = build("append_param", Map.of("param", "-Suffix"), OnScriptError.FAIL);
|
||||
SearchExecutionContext searchExecutionContext = mockContext(true, fieldType);
|
||||
Query query = new MatchQueryBuilder("test", "1-Suffix").toQuery(searchExecutionContext);
|
||||
assertThat(searcher.count(query), equalTo(1));
|
||||
|
@ -385,12 +385,12 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
|
||||
@Override
|
||||
protected KeywordScriptFieldType simpleMappedFieldType() {
|
||||
return build("read_foo", Map.of());
|
||||
return build("read_foo", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeywordScriptFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -398,13 +398,20 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
return "keyword";
|
||||
}
|
||||
|
||||
private static KeywordScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected KeywordScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new KeywordScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static StringFieldScript.Factory factory(Script script) {
|
||||
return switch (script.getIdOrCode()) {
|
||||
case "read_foo" -> (fieldName, params, lookup) -> ctx -> new StringFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "read_foo" -> (fieldName, params, lookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -412,7 +419,13 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
}
|
||||
}
|
||||
};
|
||||
case "append_param" -> (fieldName, params, lookup) -> ctx -> new StringFieldScript(fieldName, params, lookup, ctx) {
|
||||
case "append_param" -> (fieldName, params, lookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -420,16 +433,24 @@ public class KeywordScriptFieldTypeTests extends AbstractScriptFieldTypeTestCase
|
|||
}
|
||||
}
|
||||
};
|
||||
case "loop" -> (fieldName, params, lookup) -> {
|
||||
case "loop" -> (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error" -> (fieldName, params, lookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default -> throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
};
|
||||
}
|
||||
|
||||
private static KeywordScriptFieldType build(Script script) {
|
||||
return new KeywordScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,16 @@ public class KeywordScriptMapperTests extends MapperScriptTestCase<StringFieldSc
|
|||
private static StringFieldScript.Factory factory(Consumer<StringFieldScript> executor) {
|
||||
return new StringFieldScript.Factory() {
|
||||
@Override
|
||||
public StringFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public StringFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new StringFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public StringFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new StringFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new StringFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -132,7 +132,13 @@ public class LongFieldMapperTests extends WholeNumberFieldMapperTests {
|
|||
|
||||
@Override
|
||||
protected LongFieldScript.Factory emptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new LongFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {}
|
||||
};
|
||||
|
@ -140,7 +146,13 @@ public class LongFieldMapperTests extends WholeNumberFieldMapperTests {
|
|||
|
||||
@Override
|
||||
protected LongFieldScript.Factory nonEmptyFieldScript() {
|
||||
return (fieldName, params, searchLookup) -> ctx -> new LongFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return (fieldName, params, searchLookup, onScriptError) -> ctx -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(1);
|
||||
|
|
|
@ -31,10 +31,11 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class LongFieldScriptTests extends FieldScriptTestCase<LongFieldScript.Factory> {
|
||||
public static final LongFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new LongFieldScript(
|
||||
public static final LongFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -66,6 +67,7 @@ public class LongFieldScriptTests extends FieldScriptTestCase<LongFieldScript.Fa
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -100,7 +102,8 @@ public class LongFieldScriptTests extends FieldScriptTestCase<LongFieldScript.Fa
|
|||
LongFieldScript.LeafFactory leafFactory = fromSource().newFactory(
|
||||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider())
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
LongFieldScript longFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
List<Long> results = new ArrayList<>();
|
||||
|
|
|
@ -76,7 +76,7 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
List<Long> results = new ArrayList<>();
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
LongScriptFieldType ft = build("add_param", Map.of("param", 1));
|
||||
LongScriptFieldType ft = build("add_param", Map.of("param", 1), OnScriptError.FAIL);
|
||||
LongScriptFieldData ifd = ft.fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
searcher.search(new MatchAllDocsQuery(), new Collector() {
|
||||
@Override
|
||||
|
@ -132,7 +132,8 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
iw.addDocument(List.of(new StoredField("_source", new BytesRef("{\"timestamp\": [1595432181356]}"))));
|
||||
try (DirectoryReader reader = iw.getReader()) {
|
||||
IndexSearcher searcher = newUnthreadedSearcher(reader);
|
||||
LongScriptFieldData ifd = build("millis_ago", Map.of()).fielddataBuilder(mockFielddataContext()).build(null, null);
|
||||
LongScriptFieldData ifd = build("millis_ago", Map.of(), OnScriptError.FAIL).fielddataBuilder(mockFielddataContext())
|
||||
.build(null, null);
|
||||
SortField sf = ifd.sortField(null, MultiValueMode.MIN, null, false);
|
||||
TopFieldDocs docs = searcher.search(new MatchAllDocsQuery(), 3, new Sort(sf));
|
||||
assertThat(readSource(reader, docs.scoreDocs[0].doc), equalTo("{\"timestamp\": [1595432181356]}"));
|
||||
|
@ -222,7 +223,10 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
assertThat(searcher.count(simpleMappedFieldType().termQuery("1", mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(1, mockContext())), equalTo(1));
|
||||
assertThat(searcher.count(simpleMappedFieldType().termQuery(1.1, mockContext())), equalTo(0));
|
||||
assertThat(searcher.count(build("add_param", Map.of("param", 1)).termQuery(2, mockContext())), equalTo(1));
|
||||
assertThat(
|
||||
searcher.count(build("add_param", Map.of("param", 1), OnScriptError.FAIL).termQuery(2, mockContext())),
|
||||
equalTo(1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,12 +259,12 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
|
||||
@Override
|
||||
protected LongScriptFieldType simpleMappedFieldType() {
|
||||
return build("read_foo", Map.of());
|
||||
return build("read_foo", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LongScriptFieldType loopFieldType() {
|
||||
return build("loop", Map.of());
|
||||
return build("loop", Map.of(), OnScriptError.FAIL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -268,14 +272,21 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
return "long";
|
||||
}
|
||||
|
||||
private static LongScriptFieldType build(String code, Map<String, Object> params) {
|
||||
return build(new Script(ScriptType.INLINE, "test", code, params));
|
||||
protected LongScriptFieldType build(String code, Map<String, Object> params, OnScriptError onScriptError) {
|
||||
Script script = new Script(ScriptType.INLINE, "test", code, params);
|
||||
return new LongScriptFieldType("test", factory(script), script, emptyMap(), onScriptError);
|
||||
}
|
||||
|
||||
private static LongFieldScript.Factory factory(Script script) {
|
||||
switch (script.getIdOrCode()) {
|
||||
case "read_foo":
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongFieldScript(fieldName, params, lookup, ctx) {
|
||||
return (fieldName, params, lookup, onScriptError) -> (ctx) -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -284,7 +295,13 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
}
|
||||
};
|
||||
case "add_param":
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongFieldScript(fieldName, params, lookup, ctx) {
|
||||
return (fieldName, params, lookup, onScriptError) -> (ctx) -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object foo : (List<?>) lookup.source().source().get("foo")) {
|
||||
|
@ -295,7 +312,13 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
case "millis_ago":
|
||||
// Painless actually call System.currentTimeMillis. We could mock the time but this works fine too.
|
||||
long now = System.currentTimeMillis();
|
||||
return (fieldName, params, lookup) -> (ctx) -> new LongFieldScript(fieldName, params, lookup, ctx) {
|
||||
return (fieldName, params, lookup, onScriptError) -> (ctx) -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
for (Object timestamp : (List<?>) lookup.source().source().get("timestamp")) {
|
||||
|
@ -304,17 +327,26 @@ public class LongScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTest
|
|||
}
|
||||
};
|
||||
case "loop":
|
||||
return (fieldName, params, lookup) -> {
|
||||
return (fieldName, params, lookup, onScriptError) -> {
|
||||
// Indicate that this script wants the field call "test", which *is* the name of this field
|
||||
lookup.forkAndTrackFieldReferences("test");
|
||||
throw new IllegalStateException("shoud have thrown on the line above");
|
||||
throw new IllegalStateException("should have thrown on the line above");
|
||||
};
|
||||
case "error":
|
||||
return (fieldName, params, lookup, onScriptError) -> ctx -> new LongFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
onScriptError,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
throw new RuntimeException("test error");
|
||||
}
|
||||
};
|
||||
default:
|
||||
throw new IllegalArgumentException("unsupported script [" + script.getIdOrCode() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private static LongScriptFieldType build(Script script) {
|
||||
return new LongScriptFieldType("test", factory(script), script, emptyMap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ public class LongScriptMapperTests extends MapperScriptTestCase<LongFieldScript.
|
|||
private static LongFieldScript.Factory factory(Consumer<LongFieldScript> executor) {
|
||||
return new LongFieldScript.Factory() {
|
||||
@Override
|
||||
public LongFieldScript.LeafFactory newFactory(String fieldName, Map<String, Object> params, SearchLookup searchLookup) {
|
||||
public LongFieldScript.LeafFactory newFactory(
|
||||
String fieldName,
|
||||
Map<String, Object> params,
|
||||
SearchLookup searchLookup,
|
||||
OnScriptError onScriptError
|
||||
) {
|
||||
return new LongFieldScript.LeafFactory() {
|
||||
@Override
|
||||
public LongFieldScript newInstance(LeafReaderContext ctx) {
|
||||
return new LongFieldScript(fieldName, params, searchLookup, ctx) {
|
||||
return new LongFieldScript(fieldName, params, searchLookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
executor.accept(this);
|
||||
|
|
|
@ -30,10 +30,11 @@ import java.util.Map;
|
|||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class StringFieldScriptTests extends FieldScriptTestCase<StringFieldScript.Factory> {
|
||||
public static final StringFieldScript.Factory DUMMY = (fieldName, params, lookup) -> ctx -> new StringFieldScript(
|
||||
public static final StringFieldScript.Factory DUMMY = (fieldName, params, lookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
params,
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -65,6 +66,7 @@ public class StringFieldScriptTests extends FieldScriptTestCase<StringFieldScrip
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -91,6 +93,7 @@ public class StringFieldScriptTests extends FieldScriptTestCase<StringFieldScrip
|
|||
"test",
|
||||
Map.of(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -130,7 +133,8 @@ public class StringFieldScriptTests extends FieldScriptTestCase<StringFieldScrip
|
|||
StringFieldScript.LeafFactory leafFactory = fromSource().newFactory(
|
||||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider())
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
StringFieldScript stringFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
stringFieldScript.runForDoc(0);
|
||||
|
@ -159,7 +163,8 @@ public class StringFieldScriptTests extends FieldScriptTestCase<StringFieldScrip
|
|||
StringFieldScript.LeafFactory leafFactory = fromSource().newFactory(
|
||||
"field",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider())
|
||||
new SearchLookup(field -> null, (ft, lookup, fdt) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL
|
||||
);
|
||||
StringFieldScript stringFieldScript = leafFactory.newInstance(reader.leaves().get(0));
|
||||
stringFieldScript.runForDoc(0);
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.apache.lucene.index.DirectoryReader;
|
|||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.tests.index.RandomIndexWriter;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.search.lookup.SearchLookup;
|
||||
import org.elasticsearch.search.lookup.SourceLookup;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
@ -33,6 +34,7 @@ public class CompositeFieldScriptTests extends ESTestCase {
|
|||
"composite",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, ftd) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -64,6 +66,7 @@ public class CompositeFieldScriptTests extends ESTestCase {
|
|||
"composite",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, ftd) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
@ -77,6 +80,7 @@ public class CompositeFieldScriptTests extends ESTestCase {
|
|||
"composite.leaf",
|
||||
Collections.emptyMap(),
|
||||
new SearchLookup(field -> null, (ft, lookup, ftd) -> null, new SourceLookup.ReaderSourceProvider()),
|
||||
OnScriptError.FAIL,
|
||||
reader.leaves().get(0)
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.index.mapper.LuceneDocument;
|
|||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.NumberFieldMapper;
|
||||
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.script.LongFieldScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.StringFieldScript;
|
||||
|
@ -599,7 +600,7 @@ public class RangeAggregatorTests extends AggregatorTestCase {
|
|||
public void testRuntimeFieldTopLevelQueryNotOptimized() throws IOException {
|
||||
long totalDocs = (long) RangeAggregator.DOCS_PER_RANGE_TO_USE_FILTERS * 4;
|
||||
SearchLookup lookup = new SearchLookup(s -> null, (ft, l, ftd) -> null, new SourceLookup.ReaderSourceProvider());
|
||||
StringFieldScript.LeafFactory scriptFactory = ctx -> new StringFieldScript("dummy", Map.of(), lookup, ctx) {
|
||||
StringFieldScript.LeafFactory scriptFactory = ctx -> new StringFieldScript("dummy", Map.of(), lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("cat");
|
||||
|
@ -641,13 +642,19 @@ public class RangeAggregatorTests extends AggregatorTestCase {
|
|||
*/
|
||||
public void testRuntimeFieldRangesNotOptimized() throws IOException {
|
||||
long totalDocs = (long) RangeAggregator.DOCS_PER_RANGE_TO_USE_FILTERS * 4;
|
||||
LongFieldScript.Factory scriptFactory = (fieldName, params, l) -> ctx -> new LongFieldScript(fieldName, Map.of(), l, ctx) {
|
||||
LongFieldScript.Factory scriptFactory = (fieldName, params, l, onScriptError) -> ctx -> new LongFieldScript(
|
||||
fieldName,
|
||||
Map.of(),
|
||||
l,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit((long) getDoc().get(NUMBER_FIELD_NAME).get(0));
|
||||
}
|
||||
};
|
||||
MappedFieldType dummyFt = new LongScriptFieldType("dummy", scriptFactory, new Script("test"), Map.of());
|
||||
MappedFieldType dummyFt = new LongScriptFieldType("dummy", scriptFactory, new Script("test"), Map.of(), OnScriptError.FAIL);
|
||||
MappedFieldType numberFt = new NumberFieldMapper.NumberFieldType(NUMBER_FIELD_NAME, NumberFieldMapper.NumberType.INTEGER);
|
||||
debugTestCase(
|
||||
new RangeAggregationBuilder("r").field("dummy").addRange(0, 1).addRange(1, 2).addRange(2, 3),
|
||||
|
|
|
@ -60,6 +60,7 @@ import org.elasticsearch.index.mapper.NumberFieldMapper;
|
|||
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberFieldType;
|
||||
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
|
||||
import org.elasticsearch.index.mapper.ObjectMapper;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.index.mapper.ProvidedIdFieldMapper;
|
||||
import org.elasticsearch.index.mapper.RangeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.RangeType;
|
||||
|
@ -1994,7 +1995,7 @@ public class TermsAggregatorTests extends AggregatorTestCase {
|
|||
public void testRuntimeFieldTopLevelNotOptimized() throws IOException {
|
||||
long totalDocs = 500;
|
||||
SearchLookup lookup = new SearchLookup(s -> null, (ft, l, ftd) -> null, new SourceLookup.ReaderSourceProvider());
|
||||
StringFieldScript.LeafFactory scriptFactory = ctx -> new StringFieldScript("dummy", Map.of(), lookup, ctx) {
|
||||
StringFieldScript.LeafFactory scriptFactory = ctx -> new StringFieldScript("dummy", Map.of(), lookup, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("cat");
|
||||
|
@ -2043,10 +2044,11 @@ public class TermsAggregatorTests extends AggregatorTestCase {
|
|||
*/
|
||||
public void testRuntimeFieldTermsNotOptimized() throws IOException {
|
||||
long totalDocs = 500;
|
||||
StringFieldScript.Factory scriptFactory = (fieldName, params, lookup) -> ctx -> new StringFieldScript(
|
||||
StringFieldScript.Factory scriptFactory = (fieldName, params, lookup, onScriptError) -> ctx -> new StringFieldScript(
|
||||
fieldName,
|
||||
Map.of(),
|
||||
lookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
@ -2056,7 +2058,7 @@ public class TermsAggregatorTests extends AggregatorTestCase {
|
|||
};
|
||||
BytesRef[] values = new BytesRef[] { new BytesRef("stuff"), new BytesRef("more_stuff"), new BytesRef("other_stuff"), };
|
||||
MappedFieldType keywordFt = new KeywordFieldType("k", true, true, Collections.emptyMap());
|
||||
MappedFieldType dummyFt = new KeywordScriptFieldType("dummy", scriptFactory, new Script("test"), Map.of());
|
||||
MappedFieldType dummyFt = new KeywordScriptFieldType("dummy", scriptFactory, new Script("test"), Map.of(), OnScriptError.FAIL);
|
||||
debugTestCase(new TermsAggregationBuilder("t").field("dummy"), new MatchAllDocsQuery(), iw -> {
|
||||
for (int d = 0; d < totalDocs; d++) {
|
||||
BytesRef value = values[d % values.length];
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.lucene.util.BytesRef;
|
|||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.GeoUtils;
|
||||
import org.elasticsearch.index.mapper.GeoPointScriptFieldType;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.script.AbstractLongFieldScript;
|
||||
import org.elasticsearch.script.GeoPointFieldScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
|
@ -88,6 +89,7 @@ public class GeoPointScriptFieldDistanceFeatureQueryTests extends AbstractScript
|
|||
"test",
|
||||
Map.of(),
|
||||
searchLookup,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.apache.lucene.search.TopDocs;
|
|||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.tests.index.RandomIndexWriter;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.script.AbstractLongFieldScript;
|
||||
import org.elasticsearch.script.DateFieldScript;
|
||||
import org.elasticsearch.script.Script;
|
||||
|
@ -75,6 +76,7 @@ public class LongScriptFieldDistanceFeatureQueryTests extends AbstractScriptFiel
|
|||
Map.of(),
|
||||
searchLookup,
|
||||
null,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.apache.lucene.search.Rescorer;
|
|||
import org.apache.lucene.search.Scorable;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.elasticsearch.common.util.Maps;
|
||||
import org.elasticsearch.index.mapper.OnScriptError;
|
||||
import org.elasticsearch.index.query.IntervalFilterScript;
|
||||
import org.elasticsearch.index.similarity.ScriptedSimilarity.Doc;
|
||||
import org.elasticsearch.index.similarity.ScriptedSimilarity.Field;
|
||||
|
@ -269,7 +270,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
IntervalFilterScript.Factory factory = mockCompiled::createIntervalFilterScript;
|
||||
return context.factoryClazz.cast(factory);
|
||||
} else if (context.instanceClazz.equals(BooleanFieldScript.class)) {
|
||||
BooleanFieldScript.Factory booleanFieldScript = (f, p, s) -> ctx -> new BooleanFieldScript(f, p, s, ctx) {
|
||||
BooleanFieldScript.Factory booleanFieldScript = (f, p, s, onScriptError) -> ctx -> new BooleanFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(true);
|
||||
|
@ -277,7 +284,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(booleanFieldScript);
|
||||
} else if (context.instanceClazz.equals(StringFieldScript.class)) {
|
||||
StringFieldScript.Factory stringFieldScript = (f, p, s) -> ctx -> new StringFieldScript(f, p, s, ctx) {
|
||||
StringFieldScript.Factory stringFieldScript = (f, p, s, onScriptError) -> ctx -> new StringFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("test");
|
||||
|
@ -285,7 +298,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(stringFieldScript);
|
||||
} else if (context.instanceClazz.equals(LongFieldScript.class)) {
|
||||
LongFieldScript.Factory longFieldScript = (f, p, s) -> ctx -> new LongFieldScript(f, p, s, ctx) {
|
||||
LongFieldScript.Factory longFieldScript = (f, p, s, onScriptError) -> ctx -> new LongFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(1L);
|
||||
|
@ -293,7 +312,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(longFieldScript);
|
||||
} else if (context.instanceClazz.equals(DoubleFieldScript.class)) {
|
||||
DoubleFieldScript.Factory doubleFieldScript = (f, p, s) -> ctx -> new DoubleFieldScript(f, p, s, ctx) {
|
||||
DoubleFieldScript.Factory doubleFieldScript = (f, p, s, onScriptError) -> ctx -> new DoubleFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(1.2D);
|
||||
|
@ -301,7 +326,14 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(doubleFieldScript);
|
||||
} else if (context.instanceClazz.equals(DateFieldScript.class)) {
|
||||
DateFieldScript.Factory dateFieldScript = (f, p, s, formatter) -> ctx -> new DateFieldScript(f, p, s, formatter, ctx) {
|
||||
DateFieldScript.Factory dateFieldScript = (f, p, s, formatter, onScriptError) -> ctx -> new DateFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
formatter,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(123L);
|
||||
|
@ -309,7 +341,7 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(dateFieldScript);
|
||||
} else if (context.instanceClazz.equals(IpFieldScript.class)) {
|
||||
IpFieldScript.Factory ipFieldScript = (f, p, s) -> ctx -> new IpFieldScript(f, p, s, ctx) {
|
||||
IpFieldScript.Factory ipFieldScript = (f, p, s, onScriptError) -> ctx -> new IpFieldScript(f, p, s, OnScriptError.FAIL, ctx) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("127.0.0.1");
|
||||
|
@ -317,7 +349,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(ipFieldScript);
|
||||
} else if (context.instanceClazz.equals(GeoPointFieldScript.class)) {
|
||||
GeoPointFieldScript.Factory geoPointFieldScript = (f, p, s) -> ctx -> new GeoPointFieldScript(f, p, s, ctx) {
|
||||
GeoPointFieldScript.Factory geoPointFieldScript = (f, p, s, onScriptError) -> ctx -> new GeoPointFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit(1.2D, 1.2D);
|
||||
|
@ -325,7 +363,13 @@ public class MockScriptEngine implements ScriptEngine {
|
|||
};
|
||||
return context.factoryClazz.cast(geoPointFieldScript);
|
||||
} else if (context.instanceClazz.equals(CompositeFieldScript.class)) {
|
||||
CompositeFieldScript.Factory objectFieldScript = (f, p, s) -> ctx -> new CompositeFieldScript(f, p, s, ctx) {
|
||||
CompositeFieldScript.Factory objectFieldScript = (f, p, s, onScriptError) -> ctx -> new CompositeFieldScript(
|
||||
f,
|
||||
p,
|
||||
s,
|
||||
OnScriptError.FAIL,
|
||||
ctx
|
||||
) {
|
||||
@Override
|
||||
public void execute() {
|
||||
emit("field1", "value1");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue