Skip to content

Overview

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Reference page: canonical Aerospike Expression Language (AEL) lexical rules, literals, and type system, for filter and operation expressions.

Applies to

  • Aerospike Developer SDKs (Java 21+ and Python 3.10+)
  • Aerospike Database 8.2.0 or later. This applies to both filter APIs with .where(...) and operation-expression APIs: selectFrom, upsertFrom, insertFrom, updateFrom.

AEL text is parsed and compiled entirely on the server — there is no client-side AEL parser in the shipping SDKs. (An ANTLR grammar, Condition.g4, exists in both SDK repos, but it is not part of the branches these SDKs ship from; it does not run for .where(), selectFrom, upsertFrom, insertFrom, or updateFrom.) That server-side AEL compiler is what the 8.2.0 requirement gates.

Audience

Application developers authoring AEL text (Intermediate).

Prerequisites

Outcome

You can look up authoritative AEL syntax (lexical rules, literals, and types) and navigate to the rest of the AEL reference for paths, operators, functions, and control structures.

About AEL text

AEL is a text-based domain-specific language that compiles to Aerospike Database expressions. It is used for filter expressions (.where()) and as the source of read/write expressions in both Java and Python: .selectFrom() / .select_from(), .insertFrom() / .insert_from(), .updateFrom() / .update_from(), and .upsertFrom() / .upsert_from().

The same AEL text also works in Aerospike Voyager, so you can author and test an expression there, then copy it directly into application code.

For task-oriented examples of passing AEL text to SDK builders (filters on query, batch, and single-key commands; read and write operation expressions), see Author AEL expressions. That page also covers the evaluation model: the server parses and compiles AEL text on every call, and the SDKs support positional placeholders (?0, ?1, and so on) that are substituted into the AEL text on the client before it is sent.

When a filter returns nothing or a string fails to compile, see Debug AEL expressions.

In this reference

Overview (this page)

Lexical rules, literals, and the AEL type system, including TRILEAN and type suffixes.

Paths and navigation

Record and bin paths, quoted bin names, parenthesised expressions, wildcard iteration, and collection create-order suffixes.

Paths and navigation →

Selectors and loop variables

Map selectors {…}, list selectors […], inverted selections, loop variables, and selector punctuation.

Selectors and loop variables →

Operators

Comparison, in, regex match, logical operators and TRILEAN truth tables, arithmetic, integer bitwise, and precedence.

Operators →

Functions and terminals

Record metadata functions, standalone functions, GeoJSON, and path read/write terminals.

Functions and terminals →

Type inference and limits

How AEL resolves types at parse time, compile limits, and name-collision disambiguation.

Type inference and limits →

Lexical rules

  • Whitespace (spaces, tabs, newlines) is ignored between tokens.
  • Block comments only: /* … */. Comments may appear wherever whitespace is allowed. Nested block comments are not allowed.
  • Unquoted identifiers match [A-Za-z_][A-Za-z0-9_]* (bin path segments, function names, let variable names). Variable names cannot be quoted.
  • Reserved words (lowercase): and, or, not, in, let, then, when, default, unknown, error, true, false, and exclusive. These are language keywords only. Collection data type (CDT)/write verbs are not grammar keywords. They use their own identifiers (setTo, add, insertItems, and so on) instead of bare tokens like set or increment. A separate, narrower rule applies when a verb-like word is itself the name of a map key: see Quoted notation for map key names.
  • Language constants (UPPERCASE): NIL, INF (CDT ordering sentinels in list/map literal comparisons); INT, FLOAT, STRING, BOOL, BLOB, LIST, MAP, GEO, HLL (type constants, also usable as :TYPE suffixes); VECTOR (reserved for future capabilities, not used yet); * (wildcard value inside list or map literals only).
  • Function and method arguments generally use name: value syntax, for example log(value: 128, base: 2). For every function that uses named parameters, every argument must be labelled; labels may appear in any order. Exceptions:
    • Single-argument calls (abs, ceil, floor, countOneBits, geoJson, and so on) take one positional argument, for example abs(-3).
    • Variable-argument calls of the same type (min, max) are positional, for example min(3, 5, 7, 2).
    • geoCompare(a, b) is positional, and both arguments are GEO.

Literals

FormExampleNotes
Integer21, 0xff, 0b1010Decimal with optional +/-; hex and binary supported
Float3.14, .5Decimal point required; 10. is invalid — use 10.0
String'Tim', "O'Brien", 'line1\nline2'Standard escape sequences are supported: see Escape sequences below
Booleantrue, false
BLOBx'cafe', X'ffee'Even-length hex with x/X prefix
Base64b64'SGVsbG8='Invalid base64 is a parse error; b64'' is allowed
List[1, 2, 3], []Optional :SORTED / :UNSORTED suffix after ]; unsorted is the default
Map{a: 1, b: 2}, {}Keys can be strings, integers, or BLOB; optional :UNORDERED after }; key-ordered is the default
Regex/pattern/, /pat/imPerl-compatible; flags i, m, s compose by concatenation; g (global replace) is valid only on regexReplace()

Quoted strings apply everywhere quotes are allowed: expression literals, map keys, and quoted bin name segments on paths.

Escape sequences

AEL string literals support standard escape sequences:

EscapeMeaning
\\Backslash
\nNewline
\tTab
\rCarriage return
\"/\'Quote, matching the enclosing style
\0NUL
\xHHByte with hex value HH

\n/\r let a single-line source literal produce a multi-line string value: "line1\nline2" is valid. To include the enclosing quote character in a string, either escape it ('O\'Brien') or switch quote styles ("O'Brien") — both are valid.

A list literal without a suffix is unsorted. Without a suffix, a bin-level list bin is created UNSORTED on write, but a nested list that does not exist fails on access unless the path segment carries its own create-order suffix.

A map literal without a suffix is key-ordered — the same ordering as :KEY_ORDERED on a path segment. There is no :KEY_ORDERED literal suffix; key-ordered is the default. Key-value ordered maps (:KEY_VALUE_ORDERED) are not available in literal syntax; use a path create-order suffix when materializing that container on navigation.

:UNORDERED means three different things depending on where it appears, and each is independent of the others:

PositionControls
{a: 1}:UNORDERED (map literal, see Literals)The stored value’s ordering
$.m:UNORDERED.k.setTo(1) (path create-order suffix, see Collection create-order suffixes)Ordering when the path creates a missing map on navigation
$.m.getMaps():UNORDERED (postfix flag, see Postfix flags)Return shape of the read result only — does not change the stored map

For regex literal flags and syntax, see Regex literals.

Types

Concrete types

TypeDescription
INTInteger
FLOATFloating-point
STRINGUnicode string (code points for string functions)
BOOLBoolean literal values — true and false only
TRILEANThree-valued logic result — true, false, or unknown (see TRILEAN)
BLOBByte array
LISTOrdered collection
MAPKey-value collection
GEOGeoJSON value
HLLHyperLogLog bin

TRILEAN (three-valued logic)

Many predicates and logical combinations return TRILEAN, not plain BOOL. A TRILEAN result is one of:

ValueMeaning
trueDefinitively yes
falseDefinitively no
unknownIndeterminate, typically because a referenced bin, key, or path operand is absent or cannot be evaluated

unknown is not false. In filters, an unknown result usually causes the expression to fail for that record (the record is not selected). Whether an unknown result surfaces to the application as an error or simply excludes the record depends on application and API flags (for example filter vs. read mode and explain options), not on AEL syntax.

For the and / or / not truth tables, see Logical operators.

Reserved literals unknown and error (see Conditional: when) are separate value forms used in expressions such as when (…, default => unknown). They are not the same as a predicate returning unknown because a bin is missing.

Types and type suffixes

AEL is strongly typed, but types are inferred wherever possible, so an explicit :TYPE suffix is only required when the type can’t be inferred from context. For example:

  • $.bin == 'Steve' doesn’t require a type on $.bin because it can be inferred from the comparison.
  • $.a + $.b + $.c == $.d and $.b > 3.1 doesn’t require types on a, b, c, or d: b must be a FLOAT (from the comparison with 3.1), so a, c, and d must also be FLOAT from the addition and equality.
  • $.left == $.right:STRING does need a type suffix because neither bin’s type can be inferred without one.

Attach :TYPE to pin static type on a path segment or loop variable:

FormMeaning
$.bin:INTStrict typing on bin. The rest of this AEL expression carries this type forward for that bin.
$.bin:LOCAL:INTLoose typing for this occurrence only — see Use of LOCAL below
$.l.[0]:INTType the value read at that selector
$.m.key:STRINGType the value at a map key
@:INTType loop variable @ in a filter or modify body
@.price:FLOATType a field read from @
$.key():INTOptional return type on a no-arg record metadata function

Valid type names: INT, FLOAT, STRING, BOOL, BLOB, LIST, MAP, GEO, HLL. These are type pins on any path operand: bin root ($.bin:INT), navigation tail ($.m.k:STRING), loop variable (@:FLOAT), and so on.

:MAP and :LIST are type pins only. They tell the compiler to treat a path value as a map or list (required on some reads, such as wildcard-first paths — see Wildcard iteration). They do not create containers and are not create-order flags. Missing bins are materialized by write verbs (putItems, setTo, and so on) or by collection create-order suffixes on path segments.

toInt() / toFloat() and type pins: the same method names are used for string parsing (see String path functions) and numeric casting (see Path read terminals). A call such as $.amount.toFloat() does not tell the compiler whether $.amount is numeric text to parse or an integer to cast. Pin the source type on the path before the call: $.amount:INT.toFloat() casts an integer, and $.amount:STRING.toFloat() parses a string. Literals and other already-typed receivers need no suffix ("1234".toInt()).

Casing: path suffix modifiers and postfix flags use UPPERCASE (:LOCAL:, :MAP, :KEY_ORDERED, :SORTED, :NO_FAIL, and so on).

Use of LOCAL

In some rare cases, a bin such as $.amount may hold different types across records, such as INT or FLOAT. AEL normally determines the type of a bin from its first use and keeps that type for the whole expression. For example, in $.b > 3 and $.a == $.b, $.b is inferred to be INT by the first comparison, and that inference carries forward to the second comparison.

:LOCAL types each occurrence for that branch only. It does not pin a single canonical type on the bin record-wide. In a when, every branch must produce the same result type. In this example, integer amounts are cast to FLOAT so the branches unify and can be divided by $.quantity for an average price:

when (
$.amount.type() == INT => $.amount:LOCAL:INT.toFloat(),
default => $.amount:LOCAL:FLOAT
) / $.quantity:INT.toFloat()

Next steps

Paths and navigation

Record and bin paths, quoted bin names, and collection create-order suffixes.

Paths and navigation →

Author AEL expressions

Filters, read projection, and write expressions on single-key, batch, and query commands.

Author AEL expressions →