Add Painless Docs for Datetime Inputs (#43128)

This changes add documentation for accessing datetimes in Painless scripts 
from the three most common inputs of params, _source, and doc.
This commit is contained in:
Jack Conradson 2019-06-17 10:58:53 -07:00
parent 7ed23088c1
commit 04a7c84e8b
1 changed files with 244 additions and 11 deletions

View File

@ -66,9 +66,9 @@ ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
[source,Painless]
----
String datetime = '1983-10-13T22:15:30Z';
ZonedDateTime zdt = ZonedDateTime.parse(datetime);
ZonedDateTime zdt = ZonedDateTime.parse(datetime); <1>
----
Note the parse method uses ISO 8601 by default.
<1> Note the parse method uses ISO 8601 by default.
+
* parse from RFC 1123
+
@ -76,9 +76,9 @@ Note the parse method uses ISO 8601 by default.
----
String datetime = 'Thu, 13 Oct 1983 22:15:30 GMT';
ZonedDateTime zdt = ZonedDateTime.parse(datetime,
DateTimeFormatter.RFC_1123_DATE_TIME);
DateTimeFormatter.RFC_1123_DATE_TIME); <1>
----
Note the use of a built-in DateTimeFormatter.
<1> Note the use of a built-in DateTimeFormatter.
+
* parse from a custom format
+
@ -87,9 +87,9 @@ Note the use of a built-in DateTimeFormatter.
String datetime = 'custom y 1983 m 10 d 13 22:15:30 Z';
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
"'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf);
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); <1>
----
Note the use of a custom DateTimeFormatter.
<1> Note the use of a custom DateTimeFormatter.
===== Datetime Formatting Examples
@ -99,9 +99,9 @@ Note the use of a custom DateTimeFormatter.
----
ZonedDateTime zdt =
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT);
String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT); <1>
----
Note the use of a built-in DateTimeFormatter.
<1> Note the use of a built-in DateTimeFormatter.
+
* format to a custom format
+
@ -111,9 +111,9 @@ ZonedDateTime zdt =
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
"'date:' yyyy/MM/dd 'time:' HH:mm:ss");
String datetime = zdt.format(dtf);
String datetime = zdt.format(dtf); <1>
----
Note the use of a custom DateTimeFormatter.
<1> Note the use of a custom DateTimeFormatter.
==== Datetime Conversion
@ -238,7 +238,7 @@ complex datetimes there is often a method or another complex type
<<painless-api-reference-shared-ChronoUnit, ChronoUnit>>
to calculate the difference between two complex datetimes if supported.
===== Elapsed Time Examples
===== Datetime Difference Examples
* Difference in milliseconds between two numeric datetimes
+
@ -334,3 +334,236 @@ if (zdt1.isAfter(zdt2)) {
// handle condition
}
----
==== Datetime Input
There are several common ways datetimes are used as input for a script
determined by the <<painless-contexts, Painless context>>. Typically, datetime
input will be accessed from parameters specified by the user, from an original
source document, or from an indexed document.
===== Datetime Input From User Parameters
Use the {ref}/modules-scripting-using.html#_script_parameters[params section]
during script specification to pass in a numeric datetime or string datetime as
a script input. Access to user-defined parameters within a script is dependent
on the Painless context, though, the parameters are most commonly accessible
through an input called `params`.
*Examples*
* Parse a numeric datetime from user parameters to a complex datetime
+
** Input:
+
[source,JSON]
----
...
"script": {
...
"params": {
"input_datetime": 434931327000
}
}
...
----
+
** Script:
+
[source,Painless]
----
long inputDatetime = params['input_datetime'];
Instant instant = Instant.ofEpochMilli(inputDateTime);
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
----
+
* Parse a string datetime from user parameters to a complex datetime
+
** Input:
+
[source,JSON]
----
...
"script": {
...
"params": {
"input_datetime": "custom y 1983 m 10 d 13 22:15:30 Z"
}
}
...
----
+
** Script:
+
[source,Painless]
----
String datetime = params['input_datetime'];
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
"'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); <1>
----
<1> Note the use of a custom DateTimeFormatter.
===== Datetime Input From a Source Document
Use an original {ref}/mapping-source-field.html[source] document as a script
input to access a numeric datetime or string datetime for a specific field
within that document. Access to an original source document within a script is
dependent on the Painless context and is not always available. An original
source document is most commonly accessible through an input called
`ctx['_source']` or `params['_source']`.
*Examples*
* Parse a numeric datetime from a sourced document to a complex datetime
+
** Input:
+
[source,JSON]
----
{
...
"input_datetime": 434931327000
...
}
----
+
** Script:
+
[source,Painless]
----
long inputDatetime = ctx['_source']['input_datetime']; <1>
Instant instant = Instant.ofEpochMilli(inputDateTime);
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
----
<1> Note access to `_source` is dependent on the Painless context.
+
* Parse a string datetime from a sourced document to a complex datetime
+
** Input:
+
[source,JSON]
----
{
...
"input_datetime": "1983-10-13T22:15:30Z"
...
}
----
+
** Script:
+
[source,Painless]
----
String datetime = params['_source']['input_datetime']; <1>
ZonedDateTime zdt = ZonedDateTime.parse(datetime); <2>
----
<1> Note access to `_source` is dependent on the Painless context.
<2> Note the parse method uses ISO 8601 by default.
===== Datetime Input From an Indexed Document
Use an indexed document as a script input to access a complex datetime for a
specific field within that document where the field is mapped as a
{ref}/date.html[standard date] or a {ref}/date_nanos.html[nanosecond date].
Numeric datetime fields mapped as {ref}/number.html[numeric] and string
datetime fields mapped as {ref}/keyword.html[keyword] are accessible through an
indexed document as well. Access to an indexed document within a script is
dependent on the Painless context and is not always available. An indexed
document is most commonly accessible through an input called `doc`.
*Examples*
* Format a complex datetime from an indexed document to a string datetime
+
** Assumptions:
+
*** The field `input_datetime` exists in all indexes as part of the query
*** All indexed documents contain the field `input_datetime`
+
** Mappings:
+
[source,JSON]
----
{
"mappings": {
...
"properties": {
...
"input_datetime": {
"type": "date"
}
...
}
...
}
}
----
+
** Script:
+
[source,Painless]
----
def input = doc['input_datetime'].value;
String output = input.format(DateTimeFormatter.ISO_INSTANT); <1>
----
<1> Note the use of a built-in DateTimeFormatter.
+
* Find the difference between two complex datetimes from an indexed document
+
** Assumptions:
+
*** The fields `start_datetime` and `end_datetime` may *not* exist in all
indexes as part of the query
*** The fields `start_datetime` and `end_datetime` may *not* have values in all
indexed documents
+
** Mappings:
+
[source,JSON]
----
{
"mappings": {
...
"properties": {
...
"start_datetime": {
"type": "date"
},
"end_datetime": {
"type": "date"
}
...
}
...
}
}
----
+
** Script:
+
[source,Painless]
----
if (doc.containsKey('start_datetime') && doc.containsKey('end_datetime')) { <1>
if (doc['start_datetime'].size() > 0 && doc['end_datetime'].size() > 0) { <2>
def startDatetime = doc['start_datetime'].value;
def endDatetime = doc['end_datetime'].value;
long differenceInMillis =
ChronoUnit.MILLIS.between(startDateTime, endDateTime);
// handle difference in times
} else {
// handle fields without values
}
} else {
// handle index with missing fields
}
----
<1> When a query's results span multiple indexes, some indexes may not
contain a specific field. Use the `containsKey` method call on the `doc` input
to ensure a field exists as part of the index for the current document.
<2> Some field's within a document may have no values. Use the `size` method
call on a field within the `doc` input to ensure that field has at least one
value for the current document.