Browse Source

Add Datetime Now to Painless Documentation (#43852)

This change explains why Painless doesn't natively support datetime now, and 
gives examples of how to create a version of now through user-defined 
parameters.
Jack Conradson 6 years ago
parent
commit
7527157a51
1 changed files with 119 additions and 3 deletions
  1. 119 3
      docs/painless/painless-guide/painless-datetime.asciidoc

+ 119 - 3
docs/painless/painless-guide/painless-datetime.asciidoc

@@ -409,7 +409,7 @@ through an input called `params`.
 +
 [source,Painless]
 ----
-long inputDatetime = params['input_datetime'];
+long inputDateTime = params['input_datetime'];
 Instant instant = Instant.ofEpochMilli(inputDateTime);
 ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
 ----
@@ -469,7 +469,7 @@ source document is most commonly accessible through an input called
 +
 [source,Painless]
 ----
-long inputDatetime = ctx['_source']['input_datetime']; <1>
+long inputDateTime = ctx['_source']['input_datetime']; <1>
 Instant instant = Instant.ofEpochMilli(inputDateTime);
 ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
 ----
@@ -599,6 +599,122 @@ if (doc.containsKey('start') && doc.containsKey('end')) { <1>
 <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
+<2> Some fields 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.
+
+==== Datetime Now
+
+Under most Painless contexts the current datetime, `now`, is not supported.
+There are two primary reasons for this. The first is scripts are often run once
+per document, so each time the script is run a different `now` is returned. The
+second is scripts are often run in a distributed fashion without a way to
+appropriately synchronize `now`. Instead, pass in a user-defined parameter with
+either a string datetime or numeric datetime for `now`. A numeric datetime is
+preferred as there is no need to parse it for comparision.
+
+===== Datetime Now Examples
+
+* Use a numeric datetime as `now`
++
+** 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"
+            }
+            ...
+        }
+        ...
+    }
+}
+----
++
+** Input:
++
+[source,JSON]
+----
+...
+"script": {
+    ...
+    "params": {
+        "now": <generated numeric datetime in milliseconds since epoch>
+    }
+}
+...
+----
++
+** Script:
++
+[source,Painless]
+----
+long now = params['now'];
+def inputDateTime = doc['input_datetime'];
+long millisDateTime = zdt.toInstant().toEpochMilli();
+long elapsedTime = now - millisDateTime;
+----
++
+* Use a string datetime as `now`
++
+** 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"
+            }
+            ...
+        }
+        ...
+    }
+}
+----
++
+** Input:
++
+[source,JSON]
+----
+...
+"script": {
+    ...
+    "params": {
+        "now": "<generated string datetime in ISO-8601>"
+    }
+}
+...
+----
++
+** Script:
++
+[source,Painless]
+----
+String nowString = params['now'];
+ZonedDateTime nowZdt = ZonedDateTime.parse(datetime); <1>
+long now = ZonedDateTime.toInstant().toEpochMilli();
+def inputDateTime = doc['input_datetime'];
+long millisDateTime = zdt.toInstant().toEpochMilli();
+long elapsedTime = now - millisDateTime;
+----
+<1> Note this parses the same string datetime every time the script runs. Use a
+numeric datetime to avoid a significant performance hit.