Skip to content

Commit e9e232a

Browse files
authored
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.
1 parent 6d0d449 commit e9e232a

File tree

1 file changed

+244
-11
lines changed

1 file changed

+244
-11
lines changed

docs/painless/painless-guide/painless-datetime.asciidoc

Lines changed: 244 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,19 @@ ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
6666
[source,Painless]
6767
----
6868
String datetime = '1983-10-13T22:15:30Z';
69-
ZonedDateTime zdt = ZonedDateTime.parse(datetime);
69+
ZonedDateTime zdt = ZonedDateTime.parse(datetime); <1>
7070
----
71-
Note the parse method uses ISO 8601 by default.
71+
<1> Note the parse method uses ISO 8601 by default.
7272
+
7373
* parse from RFC 1123
7474
+
7575
[source,Painless]
7676
----
7777
String datetime = 'Thu, 13 Oct 1983 22:15:30 GMT';
7878
ZonedDateTime zdt = ZonedDateTime.parse(datetime,
79-
DateTimeFormatter.RFC_1123_DATE_TIME);
79+
DateTimeFormatter.RFC_1123_DATE_TIME); <1>
8080
----
81-
Note the use of a built-in DateTimeFormatter.
81+
<1> Note the use of a built-in DateTimeFormatter.
8282
+
8383
* parse from a custom format
8484
+
@@ -87,9 +87,9 @@ Note the use of a built-in DateTimeFormatter.
8787
String datetime = 'custom y 1983 m 10 d 13 22:15:30 Z';
8888
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
8989
"'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
90-
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf);
90+
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); <1>
9191
----
92-
Note the use of a custom DateTimeFormatter.
92+
<1> Note the use of a custom DateTimeFormatter.
9393

9494
===== Datetime Formatting Examples
9595

@@ -99,9 +99,9 @@ Note the use of a custom DateTimeFormatter.
9999
----
100100
ZonedDateTime zdt =
101101
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
102-
String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT);
102+
String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT); <1>
103103
----
104-
Note the use of a built-in DateTimeFormatter.
104+
<1> Note the use of a built-in DateTimeFormatter.
105105
+
106106
* format to a custom format
107107
+
@@ -111,9 +111,9 @@ ZonedDateTime zdt =
111111
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
112112
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
113113
"'date:' yyyy/MM/dd 'time:' HH:mm:ss");
114-
String datetime = zdt.format(dtf);
114+
String datetime = zdt.format(dtf); <1>
115115
----
116-
Note the use of a custom DateTimeFormatter.
116+
<1> Note the use of a custom DateTimeFormatter.
117117

118118
==== Datetime Conversion
119119

@@ -238,7 +238,7 @@ complex datetimes there is often a method or another complex type
238238
<<painless-api-reference-shared-ChronoUnit, ChronoUnit>>
239239
to calculate the difference between two complex datetimes if supported.
240240

241-
===== Elapsed Time Examples
241+
===== Datetime Difference Examples
242242

243243
* Difference in milliseconds between two numeric datetimes
244244
+
@@ -334,3 +334,236 @@ if (zdt1.isAfter(zdt2)) {
334334
// handle condition
335335
}
336336
----
337+
338+
==== Datetime Input
339+
340+
There are several common ways datetimes are used as input for a script
341+
determined by the <<painless-contexts, Painless context>>. Typically, datetime
342+
input will be accessed from parameters specified by the user, from an original
343+
source document, or from an indexed document.
344+
345+
===== Datetime Input From User Parameters
346+
347+
Use the {ref}/modules-scripting-using.html#_script_parameters[params section]
348+
during script specification to pass in a numeric datetime or string datetime as
349+
a script input. Access to user-defined parameters within a script is dependent
350+
on the Painless context, though, the parameters are most commonly accessible
351+
through an input called `params`.
352+
353+
*Examples*
354+
355+
* Parse a numeric datetime from user parameters to a complex datetime
356+
+
357+
** Input:
358+
+
359+
[source,JSON]
360+
----
361+
...
362+
"script": {
363+
...
364+
"params": {
365+
"input_datetime": 434931327000
366+
}
367+
}
368+
...
369+
----
370+
+
371+
** Script:
372+
+
373+
[source,Painless]
374+
----
375+
long inputDatetime = params['input_datetime'];
376+
Instant instant = Instant.ofEpochMilli(inputDateTime);
377+
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
378+
----
379+
+
380+
* Parse a string datetime from user parameters to a complex datetime
381+
+
382+
** Input:
383+
+
384+
[source,JSON]
385+
----
386+
...
387+
"script": {
388+
...
389+
"params": {
390+
"input_datetime": "custom y 1983 m 10 d 13 22:15:30 Z"
391+
}
392+
}
393+
...
394+
----
395+
+
396+
** Script:
397+
+
398+
[source,Painless]
399+
----
400+
String datetime = params['input_datetime'];
401+
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
402+
"'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
403+
ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); <1>
404+
----
405+
<1> Note the use of a custom DateTimeFormatter.
406+
407+
===== Datetime Input From a Source Document
408+
409+
Use an original {ref}/mapping-source-field.html[source] document as a script
410+
input to access a numeric datetime or string datetime for a specific field
411+
within that document. Access to an original source document within a script is
412+
dependent on the Painless context and is not always available. An original
413+
source document is most commonly accessible through an input called
414+
`ctx['_source']` or `params['_source']`.
415+
416+
*Examples*
417+
418+
* Parse a numeric datetime from a sourced document to a complex datetime
419+
+
420+
** Input:
421+
+
422+
[source,JSON]
423+
----
424+
{
425+
...
426+
"input_datetime": 434931327000
427+
...
428+
}
429+
----
430+
+
431+
** Script:
432+
+
433+
[source,Painless]
434+
----
435+
long inputDatetime = ctx['_source']['input_datetime']; <1>
436+
Instant instant = Instant.ofEpochMilli(inputDateTime);
437+
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
438+
----
439+
<1> Note access to `_source` is dependent on the Painless context.
440+
+
441+
* Parse a string datetime from a sourced document to a complex datetime
442+
+
443+
** Input:
444+
+
445+
[source,JSON]
446+
----
447+
{
448+
...
449+
"input_datetime": "1983-10-13T22:15:30Z"
450+
...
451+
}
452+
----
453+
+
454+
** Script:
455+
+
456+
[source,Painless]
457+
----
458+
String datetime = params['_source']['input_datetime']; <1>
459+
ZonedDateTime zdt = ZonedDateTime.parse(datetime); <2>
460+
----
461+
<1> Note access to `_source` is dependent on the Painless context.
462+
<2> Note the parse method uses ISO 8601 by default.
463+
464+
===== Datetime Input From an Indexed Document
465+
466+
Use an indexed document as a script input to access a complex datetime for a
467+
specific field within that document where the field is mapped as a
468+
{ref}/date.html[standard date] or a {ref}/date_nanos.html[nanosecond date].
469+
Numeric datetime fields mapped as {ref}/number.html[numeric] and string
470+
datetime fields mapped as {ref}/keyword.html[keyword] are accessible through an
471+
indexed document as well. Access to an indexed document within a script is
472+
dependent on the Painless context and is not always available. An indexed
473+
document is most commonly accessible through an input called `doc`.
474+
475+
*Examples*
476+
477+
* Format a complex datetime from an indexed document to a string datetime
478+
+
479+
** Assumptions:
480+
+
481+
*** The field `input_datetime` exists in all indexes as part of the query
482+
*** All indexed documents contain the field `input_datetime`
483+
+
484+
** Mappings:
485+
+
486+
[source,JSON]
487+
----
488+
{
489+
"mappings": {
490+
...
491+
"properties": {
492+
...
493+
"input_datetime": {
494+
"type": "date"
495+
}
496+
...
497+
}
498+
...
499+
}
500+
}
501+
----
502+
+
503+
** Script:
504+
+
505+
[source,Painless]
506+
----
507+
def input = doc['input_datetime'].value;
508+
String output = input.format(DateTimeFormatter.ISO_INSTANT); <1>
509+
----
510+
<1> Note the use of a built-in DateTimeFormatter.
511+
+
512+
* Find the difference between two complex datetimes from an indexed document
513+
+
514+
** Assumptions:
515+
+
516+
*** The fields `start_datetime` and `end_datetime` may *not* exist in all
517+
indexes as part of the query
518+
*** The fields `start_datetime` and `end_datetime` may *not* have values in all
519+
indexed documents
520+
+
521+
** Mappings:
522+
+
523+
[source,JSON]
524+
----
525+
{
526+
"mappings": {
527+
...
528+
"properties": {
529+
...
530+
"start_datetime": {
531+
"type": "date"
532+
},
533+
"end_datetime": {
534+
"type": "date"
535+
}
536+
...
537+
}
538+
...
539+
}
540+
}
541+
----
542+
+
543+
** Script:
544+
+
545+
[source,Painless]
546+
----
547+
if (doc.containsKey('start_datetime') && doc.containsKey('end_datetime')) { <1>
548+
549+
if (doc['start_datetime'].size() > 0 && doc['end_datetime'].size() > 0) { <2>
550+
551+
def startDatetime = doc['start_datetime'].value;
552+
def endDatetime = doc['end_datetime'].value;
553+
long differenceInMillis =
554+
ChronoUnit.MILLIS.between(startDateTime, endDateTime);
555+
556+
// handle difference in times
557+
} else {
558+
// handle fields without values
559+
}
560+
} else {
561+
// handle index with missing fields
562+
}
563+
----
564+
<1> When a query's results span multiple indexes, some indexes may not
565+
contain a specific field. Use the `containsKey` method call on the `doc` input
566+
to ensure a field exists as part of the index for the current document.
567+
<2> Some field's within a document may have no values. Use the `size` method
568+
call on a field within the `doc` input to ensure that field has at least one
569+
value for the current document.

0 commit comments

Comments
 (0)