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.
This commit is contained in:
Jack Conradson 2019-07-02 15:38:16 -07:00
parent eb73bed40d
commit 8755448a18

View File

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