Browse Source

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.
Jack Conradson 6 years ago
parent
commit
e9e232a244
1 changed files with 244 additions and 11 deletions
  1. 244 11
      docs/painless/painless-guide/painless-datetime.asciidoc

+ 244 - 11
docs/painless/painless-guide/painless-datetime.asciidoc

@@ -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.