AEL selectors and loop variables
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
Reference page: part of the AEL reference. Covers the full {…} (map) and […] (list) selector punctuation, including plural, range, and inverted forms. See Applies to on the overview page for SDK and Database version requirements.
Key range vs. index range: the marker distinguishes them, not the delimiter.
Every dimension uses the same colon (:) for ranges and comma (,) for lists. The leading marker selects the dimension:
- No marker selects by index (
{0:3}). @selects by key ({@a:d}).=selects by value ({=a:d}).#selects by rank ({#1:5}).
There is no dash (-) selector token in AEL.
/* String key range from "room1" up to (but not including) "room3": */$.rooms.{@'room1':'room3'}/* Count of entries in that range: */$.rooms.{@'room1':'room3'}.count()/* WRONG: no marker means index dimension, and "room1"/"room3" are not indexes: */$.rooms.{room1:room3} ← parse error$.m.{@'a':'d'} /* key range [a, d) */$.m.{@'a','b','c'} /* key list */$.m.{0:3} /* index range */$.m.{=10:20} /* value range */$.m.{#:3} /* top 3 by rank (lowest 3 ranks) */$.l.[1:5] /* list index range */$.l.[=1,2,3] /* list value list */$.l.[#0:3] /* list rank range */Map selectors {…}
The first character after { sets the dimension: (none) = index, @ = key, = = value, # = rank.
Selector operands are static literals only (see Collection literals are static only), not parenthesised expressions. Operand types by dimension:
| Dimension | Operand types |
|---|---|
Key (@…) | INT, STRING, BLOB literals, NIL, INF |
Value (=…) | Any scalar literal: INT, FLOAT, STRING, BOOL, BLOB, NIL, INF |
Index ({n}) | INT only — a BLOB or other non-integer literal is a parse error |
Rank (#…) | INT only — a BLOB or other non-integer literal is a parse error |
Examples with BLOB keys: $.perms.{@x'dead'}, $.caps.{@x'aa':x'ff'}, $.caps.{@x'aa',x'bb'}, $.scores.{=x'cafe'}.
In the following selector tables, — means that form isn’t available for that dimension.
| Dimension | Singular | Range | Open-start | Open-end | List | Inverted range | Inverted list |
|---|---|---|---|---|---|---|---|
| Index | {1} | {1:5} | {:5} | {1:} | — | {!1:5} | — |
| Key | 'key' or {@'key'} | {@x'ab':x'def0'} | {@:'d'} | {@'a':} | {@'a','b','c'} | {!@'a':'d'} | {!@'a','b','c'} |
| Value | {=a} | {=a:d} | {=:d} | {=a:} | {=a,b,c} | {!=a:d} | {!=1,2,3} |
| Rank | {#1} | {#1:5} | {#:5} | {#1:} | — | {!#1:5} | — |
Relative (map):
| Form | Meaning |
|---|---|
{#-1:1~ref} | Rank-relative range |
{#-2:~ref} | Rank-relative open end |
{!#-1:~ref} | Inverted rank-relative |
{0:1~key} | Index range relative to key |
{0:~key} | Index open end relative to key |
{!0:1~key} | Inverted index-relative range |
Trailing comma: {@k,} is multi-select with one key (invertible as {!@k,}); {@k} alone is singular and non-invertible (zero or one element). The same convention applies to the value dimension: {=a,} / {!=a,} is a one-element value list, while {=a} alone is singular.
Intervals: index and rank ranges use begin-inclusive, end-exclusive semantics.
List selectors […]
After [, if the next non-whitespace character is = the selector is value dimension; if # then rank; if ! then inverted (re-parse the remainder); otherwise index.
Selector operands follow the same rules as the map selectors described earlier: key/value/rank/index literal types as listed there. Examples: $.payload.[='two words'], $.payload.[=x'aa':x'ff'], $.payload.[!=172,].
In the following table, — again means that form isn’t available for that dimension.
| Dimension | Singular | Range | Open-start | Open-end | List | Inverted range | Inverted list |
|---|---|---|---|---|---|---|---|
| Index | [1] | [1:5] | [:5] | [1:] | — | [!1:5] | — |
| Value | [=a] | [=a:d] | [=:d] | [=a:] | [=a,b,c] | [!=a:d] | [!=a,b,c] |
| Rank | [#1] | [#1:5] | [#:5] | [#1:] | — | [!#1:5] | — |
Relative (list):
| Form | Meaning |
|---|---|
[#-3:-1~ref] | Rank-relative range |
[#-2:~ref] | Rank-relative open end |
[!#-3:-1~ref] | Inverted rank-relative |
Trailing comma (value dimension): [=a,] is a multi-select with one value (invertible as [!=a,]); [=a] alone is singular.
Intervals: index and rank ranges use begin-inclusive, end-exclusive semantics.
Inverted selections (prefix !)
$.m.{!@a:d} /* everything except keys a-c */$.l.[!0:3] /* everything except indices 0-2 */$.m.{!=temp,draft} /* everything except entries with these values */Loop variables
Valid only inside *[?(…)] filter predicates and .modify(…) bodies. Requires an enclosing * wildcard in scope (see Wildcard iteration).
| Form | Meaning |
|---|---|
@ | Current iteration element value (for example, the map value if iterating over map keys) |
@.field | Navigate into current element (map key) |
@.[n] | List index within current element |
@key | Parent map key (metadata; no dot) |
@index | Parent list index (metadata; no dot) |
Nested sub-expressions inside filter arguments are not allowed: no filter can nest inside another filter’s path argument. Each *[?(…)] level has its own @ scope.
$.map.{@"key1","key2","key3"}&[?(@ > 100)]$.store:MAP.*.*[?(@.inStock == true)].title$.store.book.*.price.modify(@ * 0.9)Relative selectors (map and list):
$.m.{#-1:1~ref} /* rank-relative range */$.m.{0:1~key} /* index range relative to key */$.l.[#-3:-1~ref] /* list rank-relative range */Selector punctuation quick reference
| Token | In {…} / […] |
|---|---|
| (none) | Index dimension |
@ | Map key dimension (in {…} only) |
= | Value dimension |
# | Rank dimension |
: | Range separator |
, | List / multi-select |
~ | Relative-to binding |
! immediately after { or [ | Inverted selection |
Next steps
- Operators — comparison, logical, arithmetic, and precedence
- Functions and terminals — path read and write terminals that follow a selector
- Paths and navigation — everyday map and list access