From 47fafaa98e564772f786e6a31656a2467ffb26df Mon Sep 17 00:00:00 2001 From: Kshitij Saxena Date: Tue, 28 Apr 2026 10:18:32 +0200 Subject: [PATCH 1/2] docs: enable iterating over source arrays in entity mapping --- docs/automation/entity-mapping.md | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/docs/automation/entity-mapping.md b/docs/automation/entity-mapping.md index b6af4243..3fc85e51 100644 --- a/docs/automation/entity-mapping.md +++ b/docs/automation/entity-mapping.md @@ -198,6 +198,56 @@ Use this to concatenate fields, apply mathematical expressions, or merge multipl } ``` +### `_foreach` / `_map` + +The `_foreach` operation iterates over a source array and produces a mapped output for each item. Use it when you need to map a dynamic number of items from the source entity — for example, mapping all meter readings or line items from a submission. + +| Key | Description | +|-----|-------------| +| `_foreach` | Path to the source array to iterate over | +| `_as` | Names the current item — accessed as `$` in `_copy` paths | +| `_map` | The operation to evaluate for each item | + +```json +// map all readings from a submission into a flat array +{ + "_foreach": "submission.meterReadings", + "_as": "meter", + "_map": { + "_foreach": "$meter.readings", + "_as": "reading", + "_map": { + "value": { "_copy": "$reading.value" }, + "unit": { "_copy": "$reading.unit" }, + "direction": { "_copy": "$reading.direction" }, + "reading_timestamp": { "_copy": "$meter.readingDate" }, + "read_by": { "_copy": "$meter.readBy" } + } + } +} +``` + +`_foreach` can be nested — inner results are automatically flattened into a single array. You can access both the inner alias (`$reading`), the outer alias (`$meter`), and the original source context (e.g., `meter._id`) at the same time. + +You can combine `_foreach` with `_uniq` to deduplicate results: + +```json +{ + "_foreach": "submission.items", + "_as": "item", + "_map": { + "category": { "_copy": "$item.category" } + }, + "_uniq": ["category"] +} +``` + +All other operations (`_copy`, `_template`, `_set`, `_random`, etc.) work inside `_map`. + +:::tip +Always include `_as` when using `_foreach` — without it, you can't reference the current item. +::: + ### Nesting Operations can be nested to create complex mapping behaviour: From 6e1257f1959ae5b7f4617aa148f1a3c22afacaa5 Mon Sep 17 00:00:00 2001 From: Kshitij Saxena Date: Fri, 8 May 2026 14:29:08 +0200 Subject: [PATCH 2/2] feedback: rename _foreach to _each --- docs/automation/entity-mapping.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/automation/entity-mapping.md b/docs/automation/entity-mapping.md index 3fc85e51..4f9c5be4 100644 --- a/docs/automation/entity-mapping.md +++ b/docs/automation/entity-mapping.md @@ -198,23 +198,23 @@ Use this to concatenate fields, apply mathematical expressions, or merge multipl } ``` -### `_foreach` / `_map` +### `_each` / `_map` -The `_foreach` operation iterates over a source array and produces a mapped output for each item. Use it when you need to map a dynamic number of items from the source entity — for example, mapping all meter readings or line items from a submission. +The `_each` operation iterates over a source array and produces a mapped output for each item. Use it when you need to map a dynamic number of items from the source entity — for example, mapping all meter readings or line items from a submission. | Key | Description | |-----|-------------| -| `_foreach` | Path to the source array to iterate over | +| `_each` | Path to the source array to iterate over | | `_as` | Names the current item — accessed as `$` in `_copy` paths | | `_map` | The operation to evaluate for each item | ```json // map all readings from a submission into a flat array { - "_foreach": "submission.meterReadings", + "_each": "submission.meterReadings", "_as": "meter", "_map": { - "_foreach": "$meter.readings", + "_each": "$meter.readings", "_as": "reading", "_map": { "value": { "_copy": "$reading.value" }, @@ -227,13 +227,13 @@ The `_foreach` operation iterates over a source array and produces a mapped outp } ``` -`_foreach` can be nested — inner results are automatically flattened into a single array. You can access both the inner alias (`$reading`), the outer alias (`$meter`), and the original source context (e.g., `meter._id`) at the same time. +`_each` can be nested — inner results are automatically flattened into a single array. You can access both the inner alias (`$reading`), the outer alias (`$meter`), and the original source context (e.g., `meter._id`) at the same time. -You can combine `_foreach` with `_uniq` to deduplicate results: +You can combine `_each` with `_uniq` to deduplicate results: ```json { - "_foreach": "submission.items", + "_each": "submission.items", "_as": "item", "_map": { "category": { "_copy": "$item.category" } @@ -245,7 +245,7 @@ You can combine `_foreach` with `_uniq` to deduplicate results: All other operations (`_copy`, `_template`, `_set`, `_random`, etc.) work inside `_map`. :::tip -Always include `_as` when using `_foreach` — without it, you can't reference the current item. +Always include `_as` when using `_each` — without it, you can't reference the current item. ::: ### Nesting