Skip to content

Commit ec47871

Browse files
authored
Merge pull request #313555 from sethmanheim/regrp1
1: add 2 new dataflow articles
2 parents e3a76b4 + 1317d2c commit ec47871

6 files changed

Lines changed: 527 additions & 18 deletions

File tree

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
---
2+
title: Expressions reference for data flows
3+
description: Reference for the expression language used in data flow and data flow graph transforms in Azure IoT Operations. Covers operators, functions, data types, metadata, and conditionals.
4+
author: sethmanheim
5+
ms.author: sethm
6+
ms.service: azure-iot-operations
7+
ms.subservice: azure-data-flows
8+
ms.topic: reference
9+
ms.date: 03/19/2026
10+
ai-usage: ai-assisted
11+
12+
---
13+
14+
# Expressions reference for data flows
15+
16+
[!INCLUDE [kubernetes-management-preview-note](../includes/kubernetes-management-preview-note.md)]
17+
18+
<!-- This reference applies to both [data flows](overview-dataflow.md) and [data flow graphs](concept-dataflow-graphs.md). Both use the same expression language for map, filter, and enrichment transforms. Data flow graphs also support branch and window (accumulate) transforms, which are noted where applicable. -->
19+
20+
## Positional variables
21+
22+
Each rule's `inputs` array determines the variables available in the `expression`. The first input becomes `$1`, the second becomes `$2`, and so on.
23+
24+
| Inputs | Expression | Result |
25+
|--------|-----------|--------|
26+
| `Position`, `Office` | `$1 + ", " + $2` | Concatenates Position and Office with a comma |
27+
| `temperature` | `cToF($1)` | Converts Celsius to Fahrenheit |
28+
| `temperature`, `humidity` | `$1 * $2 < 100000` | Checks a threshold against two fields |
29+
30+
If only one input is specified and no expression is provided, the value at that input is copied directly to the output.
31+
32+
## Operators
33+
34+
Expressions support the following operators, listed from highest to lowest precedence:
35+
36+
| Precedence | Operators | Description |
37+
|------------|-----------|-------------|
38+
| 1 | `!` | Logical NOT (unary) |
39+
| 2 | `^` | Exponentiation |
40+
| 3 | `*`, `/`, `%` | Multiplication, division, modulo |
41+
| 4 | `+`, `-` | Addition / string concatenation, subtraction |
42+
| 5 | `<`, `>`, `<=`, `>=` | Comparison |
43+
| 6 | `==`, `!=` | Equality, inequality |
44+
| 7 | `&&` | Logical AND |
45+
| 8 | `\|\|` | Logical OR |
46+
47+
The `+` operator concatenates strings when at least one operand is a string. Use parentheses to override default precedence.
48+
49+
Examples:
50+
51+
| Expression | Description |
52+
|-----------|-------------|
53+
| `$1 * 2 ^ 3` | Exponentiation first: `$1 * 8` |
54+
| `($1 * 2) ^ 3` | Parentheses override: multiply first |
55+
| `-$1 * 2` | Negation first, then multiply |
56+
| `$1 > 100 && $2 > 200` | Chain conditions with logical AND |
57+
58+
## Built-in functions
59+
60+
### Unit conversion functions
61+
62+
These functions accept a single numeric value and return a float.
63+
64+
| Function | Conversion | Formula |
65+
|----------|-----------|---------|
66+
| `cToF(value)` | Celsius to Fahrenheit | F = (C × 9/5) + 32 |
67+
| `fToC(value)` | Fahrenheit to Celsius | C = (F - 32) × 5/9 |
68+
| `psiToBar(value)` | PSI to bar | bar = PSI × 0.0689476 |
69+
| `barToPsi(value)` | Bar to PSI | PSI = bar / 0.0689476 |
70+
| `inToCm(value)` | Inches to centimeters | cm = in × 2.54 |
71+
| `cmToIn(value)` | Centimeters to inches | in = cm / 2.54 |
72+
| `ftToM(value)` | Feet to meters | m = ft × 0.3048 |
73+
| `mToFt(value)` | Meters to feet | ft = m / 0.3048 |
74+
| `lbToKg(value)` | Pounds to kilograms | kg = lb × 0.453592 |
75+
| `kgToLb(value)` | Kilograms to pounds | lb = kg / 0.453592 |
76+
| `galToL(value)` | US gallons to liters | L = gal × 3.78541 |
77+
| `lToGal(value)` | Liters to US gallons | gal = L / 3.78541 |
78+
79+
### Scaling and rounding functions
80+
81+
| Function | Description |
82+
|----------|-------------|
83+
| `scale(value, srcLo, srcHi, dstLo, dstHi)` | Linearly scales `value` from the source range to the destination range. All five arguments must be numeric. |
84+
| `round_n(value, decimals)` | Rounds a float to the specified number of decimal places (0 to 15). |
85+
86+
### Math functions
87+
88+
These functions come from the built-in math library.
89+
90+
| Function | Description |
91+
|----------|-------------|
92+
| `floor(value)` | Largest integer less than or equal to a number |
93+
| `round(value)` | Nearest integer, rounding half-way cases away from 0.0 |
94+
| `ceil(value)` | Smallest integer greater than or equal to a number |
95+
| `math::abs(value)` | Absolute value |
96+
| `math::sqrt(value)` | Square root (returns NaN for negative numbers) |
97+
| `math::cbrt(value)` | Cube root |
98+
| `math::ln(value)` | Natural logarithm |
99+
| `math::log2(value)` | Base-2 logarithm |
100+
| `math::log10(value)` | Base-10 logarithm |
101+
| `math::log(value, base)` | Logarithm with arbitrary base |
102+
| `math::exp(value)` | e raised to the power of value |
103+
| `math::exp2(value)` | 2 raised to the power of value |
104+
| `math::pow(base, exp)` | Raises base to the power of exp |
105+
| `math::cos(value)` | Cosine (radians) |
106+
| `math::sin(value)` | Sine (radians) |
107+
| `math::tan(value)` | Tangent (radians) |
108+
| `math::acos(value)` | Arccosine (returns radians) |
109+
| `math::asin(value)` | Arcsine (returns radians) |
110+
| `math::atan(value)` | Arctangent (returns radians) |
111+
| `math::atan2(y, x)` | Four-quadrant arctangent (returns radians) |
112+
| `math::hypot(a, b)` | Length of the hypotenuse from sides a and b |
113+
114+
### String functions
115+
116+
| Function | Description |
117+
|----------|-------------|
118+
| `len(string)` | Character length of a string, or element count of a tuple |
119+
| `str::to_lowercase(string)` | Converts to lowercase |
120+
| `str::to_uppercase(string)` | Converts to uppercase |
121+
| `str::trim(string)` | Removes leading and trailing whitespace |
122+
| `str::from(value)` | Converts a value to its string representation |
123+
| `str::substring(string, start, end)` | Extracts a substring by character index |
124+
| `str::regex_matches(string, pattern)` | Returns true if the string matches the regex pattern. Available in data flow graphs only. |
125+
| `str::regex_replace(string, pattern, replacement)` | Replaces all regex matches with the replacement string. Available in data flow graphs only. |
126+
127+
### Conditional and collection functions
128+
129+
| Function | Description |
130+
|----------|-------------|
131+
| `if(condition, trueVal, falseVal)` | Returns `trueVal` when condition is true, otherwise `falseVal` |
132+
| `min(values)` | Minimum of one or more numeric values or an array |
133+
| `max(values)` | Maximum of one or more numeric values or an array |
134+
| `contains(tuple, value)` | Returns true if the tuple contains the value |
135+
| `contains_any(tuple, candidates)` | Returns true if the tuple contains any value from the candidates tuple |
136+
| `typeof(value)` | Returns the type as a string: `"string"`, `"float"`, `"int"`, `"boolean"`, `"tuple"`, or `"empty"` |
137+
138+
### Aggregation functions (window transforms only)
139+
140+
These functions are available only in accumulation rules within window transforms. Each takes a single positional variable.
141+
142+
| Function | Returns | Empty window behavior |
143+
|----------|---------|-----------------------|
144+
| `average($n)` | Mean of numeric values | Error |
145+
| `sum($n)` | Sum of numeric values | 0.0 |
146+
| `min($n)` | Minimum numeric value | Error |
147+
| `max($n)` | Maximum numeric value | Error |
148+
| `count($n)` | Count of messages where the field exists | 0 |
149+
| `first($n)` | First value in the window | Error |
150+
| `last($n)` | Last value in the window | Error |
151+
152+
<!-- For details on using aggregation functions, see [Aggregate data over time](howto-dataflow-graphs-window.md). -->
153+
154+
## Conditional logic
155+
156+
Use the `if` function to branch logic within an expression:
157+
158+
| Expression | Description |
159+
|-----------|-------------|
160+
| `if($1 > 100, "high", "normal")` | Returns "high" when temperature exceeds 100 |
161+
| `if($2 == (), $1, $1 * $2)` | Falls back to $1 when $2 is missing |
162+
| `if($1 > 5, true, false)` | Returns a boolean based on a threshold |
163+
164+
Use `()` (the empty value) in comparisons to detect missing fields.
165+
166+
> [!TIP]
167+
> If you only need a static fallback for a missing field, the `?? <default>` syntax is simpler. See [Default values](#default-values). Reserve `if` for cases where you need to choose between computed values.
168+
169+
## Metadata fields
170+
171+
Read from and write to message metadata by using the `$metadata.` prefix in the `inputs` or `output` fields of a rule. Metadata references go in the field path, not in the expression itself.
172+
173+
| Field | Description |
174+
|-------|-------------|
175+
| `$metadata.topic` | The MQTT topic of the message |
176+
| `$metadata.user_property.<key>` | A user property on the message, identified by key |
177+
| `$metadata.system_property.content_type` | The content type system property |
178+
179+
### Read from metadata
180+
181+
To reference the source topic and a user property in an expression, list them as inputs:
182+
183+
| Input | Variable |
184+
|-------|----------|
185+
| `$metadata.topic` | `$1` |
186+
| `$metadata.user_property.device_id` | `$2` |
187+
188+
Expression: `$1 + "/" + $2`
189+
190+
### Write to metadata
191+
192+
To set a user property on the output message, use `$metadata.user_property.<key>` as the output field.
193+
194+
Setting a metadata field to an empty value (`()`) removes it. For user properties, duplicate keys are allowed.
195+
196+
Metadata fields are supported in map, filter, and branch rules. They aren't available in window (accumulate) rules.
197+
198+
## Last known value
199+
200+
Use the `? $last` suffix on an input to tell the runtime to remember the most recent value for that field. If the field is missing in the current message, the last known value is used instead.
201+
202+
| Input | Behavior |
203+
|-------|----------|
204+
| `temperature ? $last` | Uses the last known temperature if the current message has no `temperature` field |
205+
206+
The `? $last` directive is case-insensitive and supports flexible whitespace.
207+
208+
> [!IMPORTANT]
209+
> Last known values are stored in memory only. They're lost when the pod restarts and aren't shared across replicas.
210+
211+
Last known value is supported in map, filter, and branch rules. It isn't available in window (accumulate) rules.
212+
213+
## Default values
214+
215+
Use the `?? <default>` suffix on an input to provide a fallback value when the field is missing and no last known value is available. Supported default types: integer, float, boolean, string, and null.
216+
217+
| Input | Fallback |
218+
|-------|----------|
219+
| `temperature ?? 0` | Integer 0 |
220+
| `status ?? "unknown"` | String "unknown" |
221+
| `threshold ?? 98.6` | Float 98.6 |
222+
| `enabled ?? true` | Boolean true |
223+
224+
### Combine last known value and default
225+
226+
You can combine `? $last` and `?? <default>`. The runtime checks the current message first, then the last known value, then the default.
227+
228+
| Input | Evaluation order |
229+
|-------|-----------------|
230+
| `temperature ? $last ?? 0` | Current value, then last known, then 0 |
231+
232+
Default values are supported in map, filter, and branch rules. They aren't available in window (accumulate) rules.
233+
234+
## Data types
235+
236+
| Type | Description | Example |
237+
|------|-------------|---------|
238+
| Int | 64-bit signed integer | `42`, `-7` |
239+
| Float | 64-bit floating point | `3.14`, `-0.5` |
240+
| String | UTF-8 text | `"hello"` |
241+
| Bool | Boolean | `true`, `false` |
242+
| Tuple | Array of primitive values | `(1, 2, 3)` |
243+
| Empty | Missing or null value | `()` |
244+
| JSON | JSON object passed through | (can't be used in expressions) |
245+
246+
JSON objects and arrays are preserved as-is when fields are copied without an expression, but they can't be used as inputs to expression evaluation.
247+
248+
## Feature support by transform type
249+
250+
| Feature | Map | Filter | Branch | Window (accumulate) |
251+
|---------|-----|--------|--------|---------------------|
252+
| Positional variables | Yes | Yes | Yes | Yes |
253+
| Operators | Yes | Yes | Yes | Yes |
254+
| Built-in functions | Yes | Yes | Yes | Yes |
255+
| Aggregation functions | No | No | No | Yes |
256+
| `$metadata` access | Yes | Yes | Yes | No |
257+
| `$context` enrichment | Yes | Yes | Yes | No |
258+
| `? $last` | Yes | Yes | Yes | No |
259+
| `?? <default>` | Yes | Yes | Yes | No |
260+
| Wildcards | Yes | No | No | No |
261+
262+
## Related content
263+
264+
- [Map data by using data flows](concept-dataflow-mapping.md)
265+
<!-- - [Filter data in a data flow](howto-dataflow-filter.md)
266+
- [Transform data with map in data flow graphs](howto-dataflow-graphs-map.md)
267+
- [Filter and route data in data flow graphs](howto-dataflow-graphs-filter-route.md)
268+
- [Aggregate data over time](howto-dataflow-graphs-window.md)
269+
- [Enrich with external data](howto-dataflow-graphs-enrich.md) -->
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
title: Use schemas in data flow graphs
3+
description: Configure input and output schemas on node connections in data flow graphs in Azure IoT Operations.
4+
author: sethmanheim
5+
ms.author: sethm
6+
ms.service: azure-iot-operations
7+
ms.subservice: azure-data-flows
8+
ms.topic: how-to
9+
ms.date: 03/19/2026
10+
ai-usage: ai-assisted
11+
12+
#CustomerIntent: As an operator, I want to configure schemas for my data flow graphs.
13+
---
14+
15+
# Use schemas in data flow graphs
16+
17+
[!INCLUDE [kubernetes-management-preview-note](../includes/kubernetes-management-preview-note.md)]
18+
19+
Data flow graphs handle schemas differently from classic data flows. Instead of setting the schema on the source or transformation, you configure schemas on the **node connections** between nodes in the graph.
20+
21+
For information about message schema definitions, formats (JSON, Delta), and how to upload schemas, see [Understand message schemas](concept-schema-registry.md).
22+
23+
## Schema location in data flow graphs
24+
25+
In a classic data flow, schemas are configured on the source (`schemaRef` in `sourceSettings`) and transformation (`schemaRef` in `builtInTransformationSettings`). In a data flow graph, schemas are configured on the connections between nodes.
26+
27+
Each entry in the `nodeConnections` array can include a `schema` on the `from` side of the connection. This schema describes the expected format of the data flowing between those two nodes.
28+
29+
## Configure an input schema
30+
31+
To specify a schema on data entering a connection, add a `schema` field to the `from` side of the connection:
32+
33+
# [Bicep](#tab/bicep)
34+
35+
```bicep
36+
nodeConnections: [
37+
{
38+
from: {
39+
name: 'source'
40+
schema: {
41+
schemaRef: 'aio-sr://my-namespace/sensor-data:1'
42+
serializationFormat: 'Json'
43+
}
44+
}
45+
to: {
46+
name: 'transform'
47+
}
48+
}
49+
]
50+
```
51+
52+
# [Kubernetes (preview)](#tab/kubernetes)
53+
54+
```yaml
55+
nodeConnections:
56+
- from:
57+
name: source
58+
schema:
59+
schemaRef: "aio-sr://my-namespace/sensor-data:1"
60+
serializationFormat: Json
61+
to:
62+
name: transform
63+
```
64+
65+
---
66+
67+
The `schemaRef` follows the format `aio-sr://<namespace>/<name>:<version>` and references a schema stored in the [schema registry](concept-schema-registry.md).
68+
69+
Supported serialization formats:
70+
71+
| Format | Description |
72+
|--------|-------------|
73+
| `Json` | JSON format (default for MQTT and Kafka) |
74+
75+
## Configure an output schema
76+
77+
Data flow graph destinations support an `outputSchemaSettings` field to control the serialization format of the output data:
78+
79+
# [Bicep](#tab/bicep)
80+
81+
```bicep
82+
{
83+
name: 'output'
84+
nodeType: 'Destination'
85+
destinationSettings: {
86+
endpointRef: 'my-adls-endpoint'
87+
dataDestination: 'my-container'
88+
}
89+
}
90+
```
91+
92+
<!-- When using storage destinations (ADLS, Fabric, ADX), the output schema and serialization format are configured on the destination endpoint. See [Configure a data flow destination](howto-configure-dataflow-destination.md#serialize-the-output-with-a-schema). -->
93+
94+
# [Kubernetes (preview)](#tab/kubernetes)
95+
96+
```yaml
97+
- name: output
98+
nodeType: Destination
99+
destinationSettings:
100+
endpointRef: my-adls-endpoint
101+
dataDestination: my-container
102+
```
103+
104+
<!-- When using storage destinations (ADLS, Fabric, ADX), the output schema and serialization format are configured on the destination endpoint. See [Configure a data flow destination](howto-configure-dataflow-destination.md#serialize-the-output-with-a-schema). -->
105+
106+
---
107+
108+
> [!NOTE]
109+
> Data flow graphs currently support MQTT, Kafka, and OpenTelemetry endpoints only. Storage endpoints aren't supported as data flow graph destinations.
110+
111+
## Differences from data flow schemas
112+
113+
| Aspect | Data flows | Data flow graphs |
114+
|--------|-----------|-----------------|
115+
| Schema location | On source (`sourceSettings.schemaRef`) and transformation (`builtInTransformationSettings.schemaRef`) | On node connections (`nodeConnections[].from.schema`) |
116+
| Output schema | On transformation (`builtInTransformationSettings.serializationFormat`) | On destination node (`outputSchemaSettings`) |
117+
| Runtime validation | Not currently supported for source schemas | Not currently supported for source schemas |
118+
| Supported destination formats | JSON, Parquet, Delta | JSON |
119+
120+
## Related content
121+
122+
- [Understand message schemas](concept-schema-registry.md)
123+
<!-- - [Data flow graphs overview](concept-dataflow-graphs.md)
124+
- [Configure a data flow destination](howto-configure-dataflow-destination.md) -->
108 KB
Loading
165 KB
Loading

0 commit comments

Comments
 (0)