Browse Source

[DOCS] Improve ES|QL functions reference for functions A-D (#103447)

* Functions starting with A

* Functions starting with 'C'

* More 'C' functions

* Fix tests

* Fix missing snippet

* DATE_* functions

* Apply suggestions from code review

Co-authored-by: Bogdan Pintea <pintea@mailbox.org>

---------

Co-authored-by: Bogdan Pintea <pintea@mailbox.org>
Abdon Pijpelink 1 năm trước cách đây
mục cha
commit
8e0d4e1846
25 tập tin đã thay đổi với 805 bổ sung138 xóa
  1. 30 7
      docs/reference/esql/functions/abs.asciidoc
  2. 19 5
      docs/reference/esql/functions/asin.asciidoc
  3. 20 6
      docs/reference/esql/functions/atan.asciidoc
  4. 22 6
      docs/reference/esql/functions/atan2.asciidoc
  5. 78 32
      docs/reference/esql/functions/auto_bucket.asciidoc
  6. 19 2
      docs/reference/esql/functions/avg.asciidoc
  7. 27 0
      docs/reference/esql/functions/case.asciidoc
  8. 21 8
      docs/reference/esql/functions/ceil.asciidoc
  9. 24 6
      docs/reference/esql/functions/cidr_match.asciidoc
  10. 18 1
      docs/reference/esql/functions/coalesce.asciidoc
  11. 23 4
      docs/reference/esql/functions/concat.asciidoc
  12. 18 5
      docs/reference/esql/functions/cos.asciidoc
  13. 18 5
      docs/reference/esql/functions/cosh.asciidoc
  14. 34 13
      docs/reference/esql/functions/count-distinct.asciidoc
  15. 25 6
      docs/reference/esql/functions/count.asciidoc
  16. 45 4
      docs/reference/esql/functions/date_extract.asciidoc
  17. 28 5
      docs/reference/esql/functions/date_format.asciidoc
  18. 50 6
      docs/reference/esql/functions/date_trunc.asciidoc
  19. 34 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec
  20. 169 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/date.csv-spec
  21. 0 14
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec
  22. 18 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec
  23. 24 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec
  24. 10 3
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec
  25. 31 0
      x-pack/plugin/esql/qa/testFixtures/src/main/resources/math.csv-spec

+ 30 - 7
docs/reference/esql/functions/abs.asciidoc

@@ -1,18 +1,41 @@
 [discrete]
 [[esql-abs]]
 === `ABS`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/abs.svg[Embedded,opts=inline]
 
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
 Returns the absolute value.
 
-[source,esql]
+*Supported types*
+
+include::types/abs.asciidoc[]
+
+*Examples*
+
+[source.merge.styled,esql]
 ----
-FROM employees
-| KEEP first_name, last_name, height
-| EVAL abs_height = ABS(0.0 - height)
+include::{esql-specs}/math.csv-spec[tag=docsAbs]
 ----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/math.csv-spec[tag=docsAbs-result]
+|===
 
-Supported types:
-
-include::types/abs.asciidoc[]
+[source.merge.styled,esql]
+----
+include::{esql-specs}/math.csv-spec[tag=docsAbsEmployees]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/math.csv-spec[tag=docsAbsEmployees-result]
+|===

+ 19 - 5
docs/reference/esql/functions/asin.asciidoc

@@ -1,10 +1,28 @@
 [discrete]
 [[esql-asin]]
 === `ASIN`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/asin.svg[Embedded,opts=inline]
 
-Inverse https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[sine] trigonometric function.
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
+Returns the
+https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[arcsine]
+of the input numeric expression as an angle, expressed in radians.
+
+*Supported types*
+
+include::types/asin.asciidoc[]
+
+*Example*
 
 [source.merge.styled,esql]
 ----
@@ -14,7 +32,3 @@ include::{esql-specs}/floats.csv-spec[tag=asin]
 |===
 include::{esql-specs}/floats.csv-spec[tag=asin-result]
 |===
-
-Supported types:
-
-include::types/asin.asciidoc[]

+ 20 - 6
docs/reference/esql/functions/atan.asciidoc

@@ -1,10 +1,28 @@
 [discrete]
 [[esql-atan]]
 === `ATAN`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/atan.svg[Embedded,opts=inline]
 
-Inverse https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[tangent] trigonometric function.
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
+Returns the
+https://en.wikipedia.org/wiki/Inverse_trigonometric_functions[arctangent] of the
+input numeric expression as an angle, expressed in radians.
+
+*Supported types*
+
+include::types/atan.asciidoc[]
+
+*Example*
 
 [source.merge.styled,esql]
 ----
@@ -13,8 +31,4 @@ include::{esql-specs}/floats.csv-spec[tag=atan]
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
 include::{esql-specs}/floats.csv-spec[tag=atan-result]
-|===
-
-Supported types:
-
-include::types/atan.asciidoc[]
+|===

+ 22 - 6
docs/reference/esql/functions/atan2.asciidoc

@@ -1,11 +1,31 @@
 [discrete]
 [[esql-atan2]]
 === `ATAN2`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/atan2.svg[Embedded,opts=inline]
 
-The https://en.wikipedia.org/wiki/Atan2[angle] between the positive x-axis and the
-ray from the origin to the point (x , y) in the Cartesian plane.
+*Parameters*
+
+`y`::
+Numeric expression. If `null`, the function returns `null`.
+
+`x`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
+The https://en.wikipedia.org/wiki/Atan2[angle] between the positive x-axis and
+the ray from the origin to the point (x , y) in the Cartesian plane, expressed
+in radians.
+
+*Supported types*
+
+include::types/atan2.asciidoc[]
+
+*Example*
 
 [source.merge.styled,esql]
 ----
@@ -15,7 +35,3 @@ include::{esql-specs}/floats.csv-spec[tag=atan2]
 |===
 include::{esql-specs}/floats.csv-spec[tag=atan2-result]
 |===
-
-Supported types:
-
-include::types/atan2.asciidoc[]

+ 78 - 32
docs/reference/esql/functions/auto_bucket.asciidoc

@@ -1,72 +1,118 @@
 [discrete]
 [[esql-auto_bucket]]
 === `AUTO_BUCKET`
-Creates human-friendly buckets and returns a `datetime` value for each row that
-corresponds to the resulting bucket the row falls into. Combine `AUTO_BUCKET`
-with <<esql-stats-by>> to create a date histogram.
 
-You provide a target number of buckets, a start date, and an end date, and it
-picks an appropriate bucket size to generate the target number of buckets or
-fewer. For example, this asks for at most 20 buckets over a whole year, which
-picks monthly buckets:
+*Syntax*
+
+[source,esql]
+----
+AUTO_BUCKET(field, buckets, from, to)
+----
+
+*Parameters*
+
+`field`::
+Numeric or date column from which to derive buckets.
+
+`buckets`::
+Target number of buckets.
+
+`from`::
+Start of the range. Can be a number or a date expressed as a string.
+
+`to`::
+End of the range. Can be a number or a date expressed as a string.
+
+*Description*
+
+Creates human-friendly buckets and returns a value for each row that corresponds
+to the resulting bucket the row falls into. 
+
+Using a target number of buckets, a start of a range, and an end of a range,
+`AUTO_BUCKET` picks an appropriate bucket size to generate the target number of
+buckets or fewer. For example, asking for at most 20 buckets over a year results
+in monthly buckets:
 
 [source.merge.styled,esql]
 ----
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_month]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketMonth]
 ----
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_month-result]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketMonth-result]
 |===
 
 The goal isn't to provide *exactly* the target number of buckets, it's to pick a
-range that people are comfortable with that provides at most the target number of
-buckets.
+range that people are comfortable with that provides at most the target number
+of buckets.
 
-If you ask for more buckets then `AUTO_BUCKET` can pick a smaller range. For example,
-asking for at most 100 buckets in a year will get you week long buckets:
+Combine `AUTO_BUCKET` with
+<<esql-stats-by>> to create a histogram:
 
 [source.merge.styled,esql]
 ----
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_week]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketMonthlyHistogram]
 ----
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_week-result]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketMonthlyHistogram-result]
 |===
 
-`AUTO_BUCKET` does not filter any rows. It only uses the provided time range to
-pick a good bucket size. For rows with a date outside of the range, it returns a
-`datetime` that corresponds to a bucket outside the range. Combine `AUTO_BUCKET`
-with <<esql-where>> to filter rows.
+NOTE: `AUTO_BUCKET` does not create buckets that don't match any documents.
+That's why this example is missing `1985-03-01` and other dates.
 
-A more complete example might look like:
+Asking for more buckets can result in a smaller range. For example, asking for
+at most 100 buckets in a year results in weekly buckets:
 
 [source.merge.styled,esql]
 ----
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketWeeklyHistogram]
 ----
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg-result]
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketWeeklyHistogram-result]
 |===
 
-NOTE: `AUTO_BUCKET` does not create buckets that don't match any documents. That's
-why the example above is missing `1985-03-01` and other dates.
+NOTE: `AUTO_BUCKET` does not filter any rows. It only uses the provided range to
+pick a good bucket size. For rows with a value outside of the range, it returns
+a bucket value that corresponds to a bucket outside the range. Combine
+`AUTO_BUCKET` with <<esql-where>> to filter rows.
 
-==== Numeric fields
+`AUTO_BUCKET` can also operate on numeric fields. For example, to create a
+salary histogram:
 
-`auto_bucket` can also operate on numeric fields like this:
 [source.merge.styled,esql]
 ----
-include::{esql-specs}/ints.csv-spec[tag=auto_bucket]
+include::{esql-specs}/ints.csv-spec[tag=docsAutoBucketNumeric]
 ----
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-include::{esql-specs}/ints.csv-spec[tag=auto_bucket-result]
+include::{esql-specs}/ints.csv-spec[tag=docsAutoBucketNumeric-result]
 |===
 
-Unlike the example above where you are intentionally filtering on a date range,
-you rarely want to filter on a numeric range. So you have find the `min` and `max`
-separately. We don't yet have an easy way to do that automatically. Improvements
-coming!
+Unlike the earlier example that intentionally filters on a date range, you
+rarely want to filter on a numeric range. You have to find the `min` and `max`
+separately. {esql} doesn't yet have an easy way to do that automatically.
+
+*Examples*
+
+Create hourly buckets for the last 24 hours, and calculate the number of events
+per hour:
+
+
+[source.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=docsAutoBucketLast24hr]
+----
+
+Create monthly buckets for the year 1985, and calculate the average salary by
+hiring month:
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/date.csv-spec[tag=auto_bucket_in_agg-result]
+|===

+ 19 - 2
docs/reference/esql/functions/avg.asciidoc

@@ -1,8 +1,27 @@
 [discrete]
 [[esql-agg-avg]]
 === `AVG`
+
+*Syntax*
+
+[source,esql]
+----
+AVG(column)
+----
+
+`column`::
+Numeric column. If `null`, the function returns `null`.
+
+*Description*
+
 The average of a numeric field.
 
+*Supported types*
+
+The result is always a `double` no matter the input type.
+
+*Example*
+
 [source.merge.styled,esql]
 ----
 include::{esql-specs}/stats.csv-spec[tag=avg]
@@ -11,5 +30,3 @@ include::{esql-specs}/stats.csv-spec[tag=avg]
 |===
 include::{esql-specs}/stats.csv-spec[tag=avg-result]
 |===
-
-The result is always a `double` not matter the input type.

+ 27 - 0
docs/reference/esql/functions/case.asciidoc

@@ -32,6 +32,8 @@ no condition matches, the function returns `null`.
 
 *Example*
 
+Determine whether employees are monolingual, bilingual, or polyglot:
+
 [source,esql]
 [source.merge.styled,esql]
 ----
@@ -41,3 +43,28 @@ include::{esql-specs}/docs.csv-spec[tag=case]
 |===
 include::{esql-specs}/docs.csv-spec[tag=case-result]
 |===
+
+Calculate the total connection success rate based on log messages:
+
+[source,esql]
+[source.merge.styled,esql]
+----
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseSuccessRate]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseSuccessRate-result]
+|===
+
+Calculate an hourly error rate as a percentage of the total number of log
+messages:
+
+[source,esql]
+[source.merge.styled,esql]
+----
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseHourlyErrorRate]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseHourlyErrorRate-result]
+|===

+ 21 - 8
docs/reference/esql/functions/ceil.asciidoc

@@ -1,11 +1,32 @@
 [discrete]
 [[esql-ceil]]
 === `CEIL`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/ceil.svg[Embedded,opts=inline]
 
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
 Round a number up to the nearest integer.
 
+NOTE: This is a noop for `long` (including unsigned) and `integer`.
+      For `double` this picks the closest `double` value to the integer 
+      similar to {javadoc}/java.base/java/lang/Math.html#ceil(double)[Math.ceil].
+
+*Supported types*
+
+include::types/ceil.asciidoc[]
+
+
+*Example*
+
 [source.merge.styled,esql]
 ----
 include::{esql-specs}/math.csv-spec[tag=ceil]
@@ -14,11 +35,3 @@ include::{esql-specs}/math.csv-spec[tag=ceil]
 |===
 include::{esql-specs}/math.csv-spec[tag=ceil-result]
 |===
-
-NOTE: This is a noop for `long` (including unsigned) and `integer`.
-      For `double` this picks the the closest `double` value to the integer ala
-      {javadoc}/java.base/java/lang/Math.html#ceil(double)[Math.ceil].
-
-Supported types:
-
-include::types/ceil.asciidoc[]

+ 24 - 6
docs/reference/esql/functions/cidr_match.asciidoc

@@ -2,15 +2,33 @@
 [[esql-cidr_match]]
 === `CIDR_MATCH`
 
+*Syntax*
+
+[source,esql]
+----
+CIDR_MATCH(ip, block1[, ..., blockN])
+----
+
+*Parameters*
+
+`ip`::
+IP address of type `ip` (both IPv4 and IPv6 are supported).
+
+`blockX`::
+CIDR block to test the IP against.
+
+*Description*
+
 Returns `true` if the provided IP is contained in one of the provided CIDR
 blocks.
 
-`CIDR_MATCH` accepts two or more arguments. The first argument is the IP
-address of type `ip` (both IPv4 and IPv6 are supported). Subsequent arguments
-are the CIDR blocks to test the IP against.
+*Example*
 
-[source,esql]
+[source.merge.styled,esql]
 ----
-FROM hosts
-| WHERE CIDR_MATCH(ip, "127.0.0.2/32", "127.0.0.3/32")
+include::{esql-specs}/ip.csv-spec[tag=cdirMatchMultipleArgs]
 ----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/ip.csv-spec[tag=cdirMatchMultipleArgs-result]
+|===

+ 18 - 1
docs/reference/esql/functions/coalesce.asciidoc

@@ -2,7 +2,24 @@
 [[esql-coalesce]]
 === `COALESCE`
 
-Returns the first non-null value.
+*Syntax*
+
+[source,esql]
+----
+COALESCE(expression1 [, ..., expressionN])
+----
+
+*Parameters*
+
+`expressionX`::
+Expression to evaluate.
+
+*Description*
+
+Returns the first of its arguments that is not null. If all arguments are null,
+it returns `null`.
+
+*Example*
 
 [source.merge.styled,esql]
 ----

+ 23 - 4
docs/reference/esql/functions/concat.asciidoc

@@ -1,11 +1,30 @@
 [discrete]
 [[esql-concat]]
 === `CONCAT`
-Concatenates two or more strings.
+
+*Syntax*
 
 [source,esql]
 ----
-FROM employees
-| KEEP first_name, last_name, height
-| EVAL fullname = CONCAT(first_name, " ", last_name)
+CONCAT(string1, string2[, ..., stringN])
+----
+
+*Parameters*
+
+`stringX`::
+Strings to concatenate.
+
+*Description*
+
+Concatenates two or more strings.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/eval.csv-spec[tag=docsConcat]
 ----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/eval.csv-spec[tag=docsConcat-result]
+|===

+ 18 - 5
docs/reference/esql/functions/cos.asciidoc

@@ -1,10 +1,27 @@
 [discrete]
 [[esql-cos]]
 === `COS`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/cos.svg[Embedded,opts=inline]
 
-https://en.wikipedia.org/wiki/Sine_and_cosine[Cosine] trigonometric function. Input expected in radians.
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Description*
+
+Returns the https://en.wikipedia.org/wiki/Sine_and_cosine[cosine] of `n`. Input
+expected in radians.
+
+*Supported types*
+
+include::types/cos.asciidoc[]
+
+*Example*
 
 [source.merge.styled,esql]
 ----
@@ -14,7 +31,3 @@ include::{esql-specs}/floats.csv-spec[tag=cos]
 |===
 include::{esql-specs}/floats.csv-spec[tag=cos-result]
 |===
-
-Supported types:
-
-include::types/cos.asciidoc[]

+ 18 - 5
docs/reference/esql/functions/cosh.asciidoc

@@ -1,10 +1,27 @@
 [discrete]
 [[esql-cosh]]
 === `COSH`
+
+*Syntax*
+
 [.text-center]
 image::esql/functions/signature/cosh.svg[Embedded,opts=inline]
 
-https://en.wikipedia.org/wiki/Hyperbolic_functions[Cosine] hyperbolic function.
+*Parameters*
+
+`n`::
+Numeric expression. If `null`, the function returns `null`.
+
+*Supported types*
+
+include::types/cosh.asciidoc[]
+
+*Description*
+
+Returns the https://en.wikipedia.org/wiki/Hyperbolic_functions[hyperbolic
+cosine].
+
+*Example*
 
 [source.merge.styled,esql]
 ----
@@ -14,7 +31,3 @@ include::{esql-specs}/floats.csv-spec[tag=cosh]
 |===
 include::{esql-specs}/floats.csv-spec[tag=cosh-result]
 |===
-
-Supported types:
-
-include::types/cosh.asciidoc[]

+ 34 - 13
docs/reference/esql/functions/count-distinct.asciidoc

@@ -1,21 +1,28 @@
 [discrete]
 [[esql-agg-count-distinct]]
 === `COUNT_DISTINCT`
-The approximate number of distinct values.
 
-[source.merge.styled,esql]
+*Syntax*
+
+[source,esql]
 ----
-include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct]
+COUNT_DISTINCT(column[, precision])
 ----
-[%header.monospaced.styled,format=dsv,separator=|]
-|===
-include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct-result]
-|===
 
-Can take any field type as input and the result is always a `long` not matter
-the input type.
+*Parameters*
+
+`column`::
+Column for which to count the number of distinct values.
+
+`precision`::
+Precision. Refer to <<esql-agg-count-distinct-approximate>>.
+
+*Description*
+
+Returns the approximate number of distinct values.
 
 [discrete]
+[[esql-agg-count-distinct-approximate]]
 ==== Counts are approximate
 
 Computing exact counts requires loading values into a set and returning its
@@ -30,11 +37,25 @@ properties:
 
 include::../../aggregations/metrics/cardinality-aggregation.asciidoc[tag=explanation]
 
-[discrete]
-==== Precision is configurable
-
 The `COUNT_DISTINCT` function takes an optional second parameter to configure the
-precision discussed previously.
+precision.
+
+*Supported types*
+
+Can take any field type as input.
+
+*Examples*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/stats_count_distinct.csv-spec[tag=count-distinct-result]
+|===
+
+With the optional second parameter to configure the precision:
 
 [source.merge.styled,esql]
 ----

+ 25 - 6
docs/reference/esql/functions/count.asciidoc

@@ -1,7 +1,29 @@
 [discrete]
 [[esql-agg-count]]
 === `COUNT`
-Counts field values.
+
+*Syntax*
+
+[source,esql]
+----
+COUNT([input])
+----
+
+*Parameters*
+
+`input`::
+Column or literal for which to count the number of values. If omitted, returns a
+count all (the number of rows).
+
+*Description*
+
+Returns the total number (count) of input values.
+
+*Supported types*
+
+Can take any field type as input.
+
+*Examples*
 
 [source.merge.styled,esql]
 ----
@@ -12,10 +34,7 @@ include::{esql-specs}/stats.csv-spec[tag=count]
 include::{esql-specs}/stats.csv-spec[tag=count-result]
 |===
 
-Can take any field type as input and the result is always a `long` not matter
-the input type.
-
-To count the number of rows, use `COUNT(*)`:
+To count the number of rows, use `COUNT()` or `COUNT(*)`:
 
 [source.merge.styled,esql]
 ----
@@ -24,4 +43,4 @@ include::{esql-specs}/docs.csv-spec[tag=countAll]
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
 include::{esql-specs}/docs.csv-spec[tag=countAll-result]
-|===
+|===

+ 45 - 4
docs/reference/esql/functions/date_extract.asciidoc

@@ -1,15 +1,56 @@
 [discrete]
 [[esql-date_extract]]
 === `DATE_EXTRACT`
-Extracts parts of a date, like year, month, day, hour.
-The supported field types are those provided by https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoField.html[java.time.temporal.ChronoField].
+
+*Syntax*
+
+[source,esql]
+----
+DATE_EXTRACT(date_part, date)
+----
+
+*Parameters*
+
+`date_part`::
+Part of the date to extract. Can be: `aligned_day_of_week_in_month`,
+`aligned_day_of_week_in_year`, `aligned_week_of_month`, `aligned_week_of_year`,
+`ampm_of_day`, `clock_hour_of_ampm`, `clock_hour_of_day`, `day_of_month`,
+`day_of_week`, `day_of_year`, `epoch_day`, `era`, `hour_of_ampm`, `hour_of_day`,
+`instant_seconds`, `micro_of_day`, `micro_of_second`, `milli_of_day`,
+`milli_of_second`, `minute_of_day`, `minute_of_hour`, `month_of_year`,
+`nano_of_day`, `nano_of_second`, `offset_seconds`, `proleptic_month`,
+`second_of_day`, `second_of_minute`, `year`, or `year_of_era`. Refer to
+https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoField.html[java.time.temporal.ChronoField]
+for a description of these values. 
++
+If `null`, the function returns `null`.
+
+`date`::
+Date expression. If `null`, the function returns `null`.
+
+*Description*
+
+Extracts parts of a date, like year, month, day, hour. 
+
+*Examples*
 
 [source.merge.styled,esql]
 ----
-include::{esql-specs}/docs.csv-spec[tag=dateExtract]
+include::{esql-specs}/date.csv-spec[tag=dateExtract]
 ----
 [%header.monospaced.styled,format=dsv,separator=|]
 |===
-include::{esql-specs}/docs.csv-spec[tag=dateExtract-result]
+include::{esql-specs}/date.csv-spec[tag=dateExtract-result]
 |===
 
+Find all events that occurred outside of business hours (before 9 AM or after 5
+PM), on any given date:
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=docsDateExtractBusinessHours]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/date.csv-spec[tag=docsDateExtractBusinessHours-result]
+|===

+ 28 - 5
docs/reference/esql/functions/date_format.asciidoc

@@ -1,12 +1,35 @@
 [discrete]
 [[esql-date_format]]
 === `DATE_FORMAT`
-Returns a string representation of a date in the provided format. If no format
-is specified, the `yyyy-MM-dd'T'HH:mm:ss.SSSZ` format is used.
+
+*Syntax*
 
 [source,esql]
 ----
-FROM employees
-| KEEP first_name, last_name, hire_date
-| EVAL hired = DATE_FORMAT("YYYY-MM-dd", hire_date)
+DATE_FORMAT([format,] date)
+----
+
+*Parameters*
+
+`format`::
+Date format (optional).  If no format is specified, the
+`yyyy-MM-dd'T'HH:mm:ss.SSSZ` format is used.  If `null`, the function returns
+`null`.
+
+`date`::
+Date expression. If `null`, the function returns `null`.
+
+*Description*
+
+Returns a string representation of a date, in the provided format.
+
+*Example*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=docsDateFormat]
 ----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/date.csv-spec[tag=docsDateFormat-result]
+|===

+ 50 - 6
docs/reference/esql/functions/date_trunc.asciidoc

@@ -1,13 +1,57 @@
 [discrete]
 [[esql-date_trunc]]
 === `DATE_TRUNC`
-Rounds down a date to the closest interval. Intervals can be expressed using the
-<<esql-timespan-literals,timespan literal syntax>>.
+
+*Syntax*
 
 [source,esql]
 ----
-FROM employees
-| EVAL year_hired = DATE_TRUNC(1 year, hire_date)
-| STATS COUNT(emp_no) BY year_hired
-| SORT year_hired
+DATE_TRUNC(interval, date)
+----
+
+*Parameters*
+
+`interval`::
+Interval, expressed using the <<esql-timespan-literals,timespan literal
+syntax>>. If `null`, the function returns `null`.
+
+`date`::
+Date expression. If `null`, the function returns `null`.
+
+*Description*
+
+Rounds down a date to the closest interval.
+
+*Examples*
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=docsDateTrunc]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/date.csv-spec[tag=docsDateTrunc-result]
+|===
+
+Combine `DATE_TRUNC` with <<esql-stats-by>> to create date histograms. For
+example, the number of hires per year:
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/date.csv-spec[tag=docsDateTruncHistogram]
+----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/date.csv-spec[tag=docsDateTruncHistogram-result]
+|===
+
+Or an hourly error rate:
+
+[source.merge.styled,esql]
+----
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseHourlyErrorRate]
 ----
+[%header.monospaced.styled,format=dsv,separator=|]
+|===
+include::{esql-specs}/conditional.csv-spec[tag=docsCaseHourlyErrorRate-result]
+|===

+ 34 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/conditional.csv-spec

@@ -93,3 +93,37 @@ M              |10
 M              |10           
 M              |10           
 ;
+
+docsCaseSuccessRate
+// tag::docsCaseSuccessRate[]
+FROM sample_data
+| EVAL successful = CASE(
+    STARTS_WITH(message, "Connected to"), 1,
+    message == "Connection error", 0
+  )
+| STATS success_rate = AVG(successful)
+// end::docsCaseSuccessRate[]
+;
+
+// tag::docsCaseSuccessRate-result[]
+success_rate:double
+0.5
+// end::docsCaseSuccessRate-result[]
+;
+
+docsCaseHourlyErrorRate
+// tag::docsCaseHourlyErrorRate[]
+FROM sample_data
+| EVAL error = CASE(message LIKE "*error*", 1, 0)
+| EVAL hour = DATE_TRUNC(1 hour, @timestamp)
+| STATS error_rate = AVG(error) by hour
+| SORT hour
+// end::docsCaseHourlyErrorRate[]
+;
+
+// tag::docsCaseHourlyErrorRate-result[]
+error_rate:double | hour:date
+0.0            |2023-10-23T12:00:00.000Z
+0.6            |2023-10-23T13:00:00.000Z
+// end::docsCaseHourlyErrorRate-result[]
+;

+ 169 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/date.csv-spec

@@ -726,6 +726,86 @@ birth_date:datetime
 1953-04-21T00:00:00.000Z
 ;
 
+docsAutoBucketMonth
+//tag::docsAutoBucketMonth[]
+FROM employees
+| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
+| EVAL month = AUTO_BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
+| KEEP hire_date, month
+| SORT hire_date
+//end::docsAutoBucketMonth[]
+;
+
+//tag::docsAutoBucketMonth-result[]
+   hire_date:date    |    month:date
+1985-02-18T00:00:00.000Z|1985-02-01T00:00:00.000Z
+1985-02-24T00:00:00.000Z|1985-02-01T00:00:00.000Z
+1985-05-13T00:00:00.000Z|1985-05-01T00:00:00.000Z
+1985-07-09T00:00:00.000Z|1985-07-01T00:00:00.000Z
+1985-09-17T00:00:00.000Z|1985-09-01T00:00:00.000Z
+1985-10-14T00:00:00.000Z|1985-10-01T00:00:00.000Z
+1985-10-20T00:00:00.000Z|1985-10-01T00:00:00.000Z
+1985-11-19T00:00:00.000Z|1985-11-01T00:00:00.000Z
+1985-11-20T00:00:00.000Z|1985-11-01T00:00:00.000Z
+1985-11-20T00:00:00.000Z|1985-11-01T00:00:00.000Z
+1985-11-21T00:00:00.000Z|1985-11-01T00:00:00.000Z
+//end::docsAutoBucketMonth-result[]
+;
+
+docsAutoBucketMonthlyHistogram
+//tag::docsAutoBucketMonthlyHistogram[]
+FROM employees
+| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
+| EVAL month = AUTO_BUCKET(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
+| STATS hires_per_month = COUNT(*) BY month
+| SORT month
+//end::docsAutoBucketMonthlyHistogram[]
+;
+
+//tag::docsAutoBucketMonthlyHistogram-result[]
+  hires_per_month:long    |    month:date
+2              |1985-02-01T00:00:00.000Z
+1              |1985-05-01T00:00:00.000Z
+1              |1985-07-01T00:00:00.000Z
+1              |1985-09-01T00:00:00.000Z
+2              |1985-10-01T00:00:00.000Z
+4              |1985-11-01T00:00:00.000Z
+//end::docsAutoBucketMonthlyHistogram-result[]
+;
+
+docsAutoBucketWeeklyHistogram
+//tag::docsAutoBucketWeeklyHistogram[]
+FROM employees
+| WHERE hire_date >= "1985-01-01T00:00:00Z" AND hire_date < "1986-01-01T00:00:00Z"
+| EVAL week = AUTO_BUCKET(hire_date, 100, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")
+| STATS hires_per_week = COUNT(*) BY week
+| SORT week
+//end::docsAutoBucketWeeklyHistogram[]
+;
+
+//tag::docsAutoBucketWeeklyHistogram-result[]
+  hires_per_week:long    |    week:date
+2              |1985-02-18T00:00:00.000Z
+1              |1985-05-13T00:00:00.000Z
+1              |1985-07-08T00:00:00.000Z
+1              |1985-09-16T00:00:00.000Z
+2              |1985-10-14T00:00:00.000Z
+4              |1985-11-18T00:00:00.000Z
+//end::docsAutoBucketWeeklyHistogram-result[]
+;
+
+docsAutoBucketLast24hr
+//tag::docsAutoBucketLast24hr[]
+FROM sample_data 
+| WHERE @timestamp >= NOW() - 1 day and @timestamp < NOW()
+| EVAL bucket = AUTO_BUCKET(@timestamp, 25, DATE_FORMAT(NOW() - 1 day), DATE_FORMAT(NOW()))
+| STATS COUNT(*) BY bucket
+//end::docsAutoBucketLast24hr[]
+;
+
+   COUNT(*):long    |    bucket:date
+;
+
 docsGettingStartedAutoBucket
 // tag::gs-auto_bucket[]
 FROM sample_data
@@ -767,3 +847,92 @@ median_duration:double | bucket:date
 3107561.0              |2023-10-23T12:00:00.000Z
 1756467.0              |2023-10-23T13:00:00.000Z
 ;
+
+dateExtract
+// tag::dateExtract[]
+ROW date = DATE_PARSE("yyyy-MM-dd", "2022-05-06")
+| EVAL year = DATE_EXTRACT("year", date)
+// end::dateExtract[]
+;
+
+// tag::dateExtract-result[]
+date:date                 | year:long
+2022-05-06T00:00:00.000Z  | 2022
+// end::dateExtract-result[]
+;
+
+docsDateExtractBusinessHours
+// tag::docsDateExtractBusinessHours[]
+FROM sample_data
+| WHERE DATE_EXTRACT("hour_of_day", @timestamp) < 9 AND DATE_EXTRACT("hour_of_day", @timestamp) >= 17
+// end::docsDateExtractBusinessHours[]
+;
+
+// tag::docsDateExtractBusinessHours-result[]
+@timestamp:date       |   client_ip:ip   |event_duration:long |       message:keyword
+// end::docsDateExtractBusinessHours-result[]
+;
+
+docsDateFormat
+// tag::docsDateFormat[]
+FROM employees
+| KEEP first_name, last_name, hire_date
+| EVAL hired = DATE_FORMAT("YYYY-MM-dd", hire_date)
+// end::docsDateFormat[]
+| SORT first_name
+| LIMIT 3
+;
+
+// tag::docsDateFormat-result[]
+first_name:keyword   |   last_name:keyword   | hire_date:date           | hired:keyword
+Alejandro      |McAlpine       |1991-06-26T00:00:00.000Z|1991-06-26     
+Amabile        |Gomatam        |1992-11-18T00:00:00.000Z|1992-11-18     
+Anneke         |Preusig        |1989-06-02T00:00:00.000Z|1989-06-02     
+// end::docsDateFormat-result[]
+;
+
+docsDateTrunc
+// tag::docsDateTrunc[]
+FROM employees
+| KEEP first_name, last_name, hire_date
+| EVAL year_hired = DATE_TRUNC(1 year, hire_date)
+// end::docsDateTrunc[]
+| SORT first_name
+| LIMIT 3
+;
+
+// tag::docsDateTrunc-result[]
+first_name:keyword   |   last_name:keyword   | hire_date:date           | year_hired:date
+Alejandro      |McAlpine       |1991-06-26T00:00:00.000Z|1991-01-01T00:00:00.000Z
+Amabile        |Gomatam        |1992-11-18T00:00:00.000Z|1992-01-01T00:00:00.000Z
+Anneke         |Preusig        |1989-06-02T00:00:00.000Z|1989-01-01T00:00:00.000Z
+// end::docsDateTrunc-result[]
+;
+
+docsDateTruncHistogram
+// tag::docsDateTruncHistogram[]
+FROM employees
+| EVAL year = DATE_TRUNC(1 year, hire_date)
+| STATS hires = COUNT(emp_no) BY year
+| SORT year
+// end::docsDateTruncHistogram[]
+;
+
+// tag::docsDateTruncHistogram-result[]
+hires:long     | year:date
+11             |1985-01-01T00:00:00.000Z
+11             |1986-01-01T00:00:00.000Z
+15             |1987-01-01T00:00:00.000Z
+9              |1988-01-01T00:00:00.000Z
+13             |1989-01-01T00:00:00.000Z
+12             |1990-01-01T00:00:00.000Z
+6              |1991-01-01T00:00:00.000Z
+8              |1992-01-01T00:00:00.000Z
+3              |1993-01-01T00:00:00.000Z
+4              |1994-01-01T00:00:00.000Z
+5              |1995-01-01T00:00:00.000Z
+1              |1996-01-01T00:00:00.000Z
+1              |1997-01-01T00:00:00.000Z
+1              |1999-01-01T00:00:00.000Z
+// end::docsDateTruncHistogram-result[]
+;

+ 0 - 14
x-pack/plugin/esql/qa/testFixtures/src/main/resources/docs.csv-spec

@@ -290,20 +290,6 @@ Udi            |Jansch         |1.93
 Uri            |Lenart         |1.75
 ;
 
-
-dateExtract
-// tag::dateExtract[]
-ROW date = DATE_PARSE("yyyy-MM-dd", "2022-05-06")
-| EVAL year = DATE_EXTRACT("year", date)
-// end::dateExtract[]
-;
-
-// tag::dateExtract-result[]
-date:date                 | year:long
-2022-05-06T00:00:00.000Z  | 2022
-// end::dateExtract-result[]
-;
-
 docsSubstring
 // tag::substring[]
 FROM employees

+ 18 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/eval.csv-spec

@@ -222,6 +222,24 @@ emp_no:integer  | foldable:keyword | folded_mv:keyword
 10002           | "foo,bar"        | [foo, bar]
 ;
 
+docsConcat
+// tag::docsConcat[]
+FROM employees
+| KEEP first_name, last_name
+| EVAL fullname = CONCAT(first_name, " ", last_name)
+// end::docsConcat[]
+| SORT first_name
+| LIMIT 3
+;
+
+// tag::docsConcat-result[]
+first_name:keyword   |   last_name:keyword   |     fullname:keyword
+Alejandro      |McAlpine       |Alejandro McAlpine
+Amabile        |Gomatam        |Amabile Gomatam
+Anneke         |Preusig        |Anneke Preusig
+// end::docsConcat-result[]
+;
+
 docsGettingStartedEval
 // tag::gs-eval[]
 FROM sample_data

+ 24 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/ints.csv-spec

@@ -410,6 +410,30 @@ hire_date:date           | salary:integer | bs:double
 // end::auto_bucket-result[]
 ;
 
+docsAutoBucketNumeric
+//tag::docsAutoBucketNumeric[]
+FROM employees
+| EVAL bs = AUTO_BUCKET(salary, 20, 25324, 74999)
+| STATS COUNT(*) by bs
+| SORT bs
+//end::docsAutoBucketNumeric[]
+;
+
+//tag::docsAutoBucketNumeric-result[]
+   COUNT(*):long    |    bs:double
+9              |25000.0        
+9              |30000.0        
+18             |35000.0        
+11             |40000.0        
+11             |45000.0        
+10             |50000.0        
+7              |55000.0        
+9              |60000.0        
+8              |65000.0        
+8              |70000.0        
+//end::docsAutoBucketNumeric-result[]
+;
+
 cos
 ROW a=2 | EVAL cos=COS(a);
 

+ 10 - 3
x-pack/plugin/esql/qa/testFixtures/src/main/resources/ip.csv-spec

@@ -178,14 +178,21 @@ eth2           |epsilon        |[fe81::cae2:65ff:fece:feb9, fe82::cae2:65ff:fece
 ;
 
 cdirMatchMultipleArgs#[skip:-8.11.99, reason:Lucene multivalue warning introduced in 8.12 only]
-from hosts | where cidr_match(ip1, "127.0.0.2/32", "127.0.0.3/32") | keep card, host, ip0, ip1;
+//tag::cdirMatchMultipleArgs[]
+FROM hosts 
+| WHERE CIDR_MATCH(ip1, "127.0.0.2/32", "127.0.0.3/32") 
+| KEEP card, host, ip0, ip1
+//end::cdirMatchMultipleArgs[]
+;
 ignoreOrder:true
-warning:Line 1:20: evaluation of [cidr_match(ip1, \"127.0.0.2/32\", \"127.0.0.3/32\")] failed, treating result as null. Only first 20 failures recorded.
-warning:Line 1:20: java.lang.IllegalArgumentException: single-value function encountered multi-value
+warning:Line 2:9: evaluation of [CIDR_MATCH(ip1, \"127.0.0.2/32\", \"127.0.0.3/32\")] failed, treating result as null. Only first 20 failures recorded.
+warning:Line 2:9: java.lang.IllegalArgumentException: single-value function encountered multi-value
 
+//tag::cdirMatchMultipleArgs-result[]
 card:keyword   |host:keyword   |ip0:ip                   |ip1:ip
 eth1           |beta           |127.0.0.1                |127.0.0.2
 eth0           |gamma          |fe80::cae2:65ff:fece:feb9|127.0.0.3
+//end::cdirMatchMultipleArgs-result[]
 ;
 
 cidrMatchFunctionArg#[skip:-8.11.99, reason:Lucene multivalue warning introduced in 8.12 only]

+ 31 - 0
x-pack/plugin/esql/qa/testFixtures/src/main/resources/math.csv-spec

@@ -1118,3 +1118,34 @@ emp_no:integer | min_plus_max:integer | are_equal:boolean
          10004 |                    7 | false
          10005 |                    3 | false
 ;
+
+docsAbs
+//tag::docsAbs[]
+ROW number = -1.0 
+| EVAL abs_number = ABS(number)
+//end::docsAbs[]
+;
+
+//tag::docsAbs-result[]
+number:double  |  abs_number:double
+-1.0           |1.0    
+//end::docsAbs-result[]
+;
+
+docsAbsEmployees
+//tag::docsAbsEmployees[]
+FROM employees
+| KEEP first_name, last_name, height
+| EVAL abs_height = ABS(0.0 - height)
+//end::docsAbsEmployees[]
+| SORT first_name
+| LIMIT 3
+;
+
+//tag::docsAbsEmployees-result[]
+first_name:keyword   |   last_name:keyword | height:double  |  abs_height:double
+Alejandro      |McAlpine       |1.48           |1.48           
+Amabile        |Gomatam        |2.09           |2.09           
+Anneke         |Preusig        |1.56           |1.56     
+//end::docsAbsEmployees-result[]
+;