forked from confluentinc/ksql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add documentation for using lambda functions (confluentinc#7092)
* docs: add documentation for using lambda functions * Adding lambda example docs * Updates for reduce * Review update * Apply suggestions from code review Co-authored-by: Jim Galasyn <jim.galasyn@confluent.io> * Review updates - adding index cards * language clean-up Co-authored-by: Steven Zhang <stevenz@confluent.io> Co-authored-by: Jim Galasyn <jim.galasyn@confluent.io>
- Loading branch information
1 parent
170a3c0
commit 8f684da
Showing
6 changed files
with
314 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--- | ||
layout: page | ||
title: Lambda Functions | ||
keywords: ksqldb, function, udf, lambda | ||
--- | ||
|
||
# Lambda Functions | ||
|
||
Use lambda functions, or "lambdas" for short, to express simple inline functions that can be applied to input values in various ways. | ||
For example, you could apply a lambda function to each element of a collection, resulting in a transformed output collection. | ||
Also, you can use lambdas to filter the elements of a collection, or reduce a collection to a single value. | ||
The advantage of a lambda is that you can express user-defined functionality in a way that doesn’t require implementing a full [UDF](/how-to-guides/create-a-user-defined-function). | ||
|
||
Learn how to use lambda functions in the [how-to guide](/how-to-guides/use-lambda-functions-in-udfs). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
--- | ||
layout: page | ||
title: How to transform columns with structured data. | ||
tagline: Transform columns of structured data without user-defined functions. | ||
description: ksqlDB can compose existing functions to create new expressions over structured data | ||
keywords: function, lambda, aggregation, user-defined function, ksqlDB | ||
--- | ||
# Use lambda functions | ||
|
||
## Context | ||
|
||
You want to transform a column with structured data in a particular way, but there doesn't | ||
exist a built-in function that suits your needs and you're unable to implement and deploy a | ||
user-defined function. ksqlDB is capable of composing existing functions to create | ||
new expressions over structured data. These are called lambda functions. | ||
|
||
## In action | ||
```sql | ||
CREATE STREAM stream1 ( | ||
id INT, | ||
lambda_map MAP<STRING, INTEGER> | ||
) WITH ( | ||
kafka_topic = 'stream1', | ||
partitions = 1, | ||
value_format = 'avro' | ||
); | ||
|
||
CREATE STREAM output AS | ||
SELECT id, | ||
TRANSFORM(lambda_map, (k, v) => UCASE(k), (k, v) => v + 5) | ||
FROM stream1 | ||
EMIT CHANGES; | ||
``` | ||
|
||
## Syntax | ||
|
||
The arguments for the lambda function are separated from the body of the lambda with the lambda operator, `=>`. | ||
|
||
When there are two or more arguments, you must enclose the arguments with parentheses. Parentheses are optional for lambda functions with one argument. | ||
|
||
Currently, ksqlDB supports up to three arguments in a single lambda function. | ||
|
||
```sql | ||
x => x + 5 | ||
|
||
(x,y) => x - y | ||
|
||
(x,y,z) => z AND x OR y | ||
``` | ||
|
||
## Invocation UDFs | ||
|
||
Lambda functions must be used inside designated invocation functions. These are the available Invocations: | ||
|
||
- [TRANSFORM](/developer-guide/ksqldb-reference/scalar-functions#TRANSFORM) | ||
- [REDUCE](/developer-guide/ksqldb-reference/scalar-functions#REDUCE) | ||
- [FILTER](/developer-guide/ksqldb-reference/scalar-functions#FILTER) | ||
|
||
## Create a lambda-compatible stream | ||
Invocation functions require either a map or array input. The following example creates a stream | ||
with a column type of `MAP<STRING, INTEGER>`. | ||
```sql | ||
CREATE STREAM stream1 ( | ||
id INT, | ||
lambda_map MAP<STRING, INTEGER> | ||
) WITH ( | ||
kafka_topic = 'stream1', | ||
partitions = 1, | ||
value_format = 'avro' | ||
); | ||
``` | ||
|
||
## Apply a lambda invocation function | ||
A lambda invocation function is a [scalar UDF](/developer-guide/ksqldb-reference/scalar-functions), and you use it like other scalar functions. | ||
|
||
The following example lambda function transforms both the key and value of a map and produces a new map. A built-in UDF transforms the key | ||
into an uppercase string using a built in UDF, and the value is transformed through addition. The order of the variables | ||
is important: the first item in the arguments list, named `k` in this example, is treated as the key, and the second, | ||
named `v` in this example, is treated as the value. Pay attention to this if your map has different types. | ||
Note that `transform` on a map requires two lambda functions, while `transform` on an array requires one. | ||
```sql | ||
CREATE STREAM output AS | ||
SELECT id, | ||
TRANSFORM(lambda_map, (k, v) => UCASE(k), (k, v) => v + 5) | ||
FROM stream1; | ||
``` | ||
|
||
Insert some values into `stream1`. | ||
```sql | ||
INSERT INTO stream1 ( | ||
id, lambda_map | ||
) VALUES ( | ||
3, MAP("hello":= 15, "goodbye":= -5) | ||
); | ||
``` | ||
|
||
Query the output. | ||
```sql | ||
SELECT * FROM output AS final_output; | ||
``` | ||
|
||
Your output should resemble: | ||
```sql | ||
+------------------------------+------------------------------+ | ||
|id |final_output | | ||
+------------------------------+------------------------------+ | ||
|3 |{HELLO: 20} | | ||
|4 |{GOODBYE: 0} | | ||
``` | ||
|
||
## Use a reduce lambda invocation function | ||
The following example creates a stream with a column type `ARRAY<INTEGER>` and applies the `reduce` lambda | ||
invocation function. | ||
```sql | ||
CREATE STREAM stream1 ( | ||
id INT, | ||
lambda_arr ARRAY<INTEGER> | ||
) WITH ( | ||
kafka_topic = 'stream1', | ||
partitions = 1, | ||
value_format = 'avro' | ||
); | ||
|
||
CREATE STREAM output AS | ||
SELECT id, | ||
REDUCE(lambda_arr, 2, (s, x) => ceil(x/s)) | ||
FROM stream1 | ||
EMIT CHANGES; | ||
``` | ||
Insert some values into `stream1`. | ||
```sql | ||
INSERT INTO stream1 ( | ||
id, lambda_arr | ||
) VALUES ( | ||
1, ARRAY(2, 3, 4, 5) | ||
); | ||
``` | ||
|
||
Query the output. | ||
```sql | ||
SELECT * FROM output AS final_output; | ||
``` | ||
|
||
You should see something similar to: | ||
```sql | ||
+------------------------------+------------------------------+ | ||
|id |final_output | | ||
+------------------------------+------------------------------+ | ||
|1 |{output:3} | | ||
``` | ||
|
||
## Use a filter lambda invocation function | ||
Create a stream with a column type `MAP<STRING, INTEGER>`and apply the `filter` lambda | ||
invocation function. | ||
```sql | ||
CREATE STREAM stream1 ( | ||
id INT, | ||
lambda_map MAP<STRING, INTEGER> | ||
) WITH ( | ||
kafka_topic = 'stream1', | ||
partitions = 1, | ||
value_format = 'avro' | ||
); | ||
|
||
CREATE STREAM output AS | ||
SELECT id, | ||
FILTER(lambda_map, (k, v) => instr(k, 'name') > 0 AND v != 0) | ||
FROM stream1 | ||
EMIT CHANGES; | ||
``` | ||
Insert some values into `stream1`. | ||
```sql | ||
INSERT INTO stream1 ( | ||
id, lambda_arr | ||
) VALUES ( | ||
1, MAP("first name":= 15, "middle":= 25, "last name":= 0, "alt name":= 33) | ||
); | ||
``` | ||
|
||
Query the output. | ||
```sql | ||
SELECT * FROM output AS final_output; | ||
``` | ||
|
||
Your output should resemble: | ||
```sql | ||
+------------------------------+-----------------------------------------------+ | ||
|id |final_output | | ||
+------------------------------+-----------------------------------------------+ | ||
|1 |{first name: 15, alt name: 33} | | ||
``` | ||
|
||
## Advanced lambda use cases | ||
the following example creates a stream with a column type `MAP<STRING, ARRAY<DECIMAL(2,3)>` and applies the `transform` | ||
lambda invocation function with a nested `transform` lambda invocation function. | ||
```sql | ||
CREATE STREAM stream1 ( | ||
id INT, | ||
lambda_map MAP<STRING, ARRAY<DECIMAL(2,3)>> | ||
) WITH ( | ||
kafka_topic = 'stream1', | ||
partitions = 1, | ||
value_format = 'avro' | ||
); | ||
|
||
CREATE STREAM output AS | ||
SELECT id, | ||
TRANSFORM(lambda_map, (k, v) => concat(k, '_new') (k, v) => transform(v, x => round(x))) | ||
FROM stream1 | ||
EMIT CHANGES; | ||
``` | ||
Insert some values into `stream1`. | ||
```sql | ||
INSERT INTO stream1 ( | ||
id, lambda_arr | ||
) VALUES ( | ||
1, MAP("Mary":= ARRAY[1.23, 3.65, 8.45], "Jose":= ARRAY[5.23, 1.65]}) | ||
); | ||
``` | ||
|
||
Query the output. | ||
```sql | ||
SELECT * FROM output AS final_output; | ||
``` | ||
|
||
Your output should resemble: | ||
```sql | ||
+------------------------------+----------------------------------------------------------+ | ||
|id |final_output | | ||
+------------------------------+----------------------------------------------------------+ | ||
|1 |{Mary_new: [1, 4, 8], Jose_new: [5, 2]} | | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters