Skip to content

Declare and control-flow

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Aerospike expressions for declaring variables enable more advanced control-flow within database queries.

This guide explains how to define and use variables using expressions like cond, unknown, let, def, and var, allowing you to evaluate conditions, manage control-flow, and reuse values efficiently. These expressions can simplify complex logic and improve query performance.

The Developer SDK’s AEL text syntax expresses the same control flow with let ... then and when ... default.

Each operation’s Example shows the code in nine tabs: Aerospike Expression Language (AEL) text on the Java SDK and Python SDK tabs, and the Exp builder on the other seven. See the AEL reference for AEL grammar.

Ops

cond

cond(condition0, action0, condition1, action1, ..., default-action)
Description

Multi-way branch expression, similar in spirit to a switch that picks the first matching case, except each case is its own Boolean test (like an if-else if-else chain). Alternating condition and action operands, plus one final default action. Conditions are evaluated in order; the first that is true causes the following action to be evaluated and returned as the value of cond, and no later conditions or actions run. If every condition is false, the default action is evaluated and returned. All actions (including the default) must produce the same result type, except where unknown is allowed by the type rules.

Arguments
NameTypeDescription
condition0boolean

First test. If it is true, action0 becomes the value of the cond and nothing after it is evaluated.

action0any

Value of the cond when condition0 is true.

condition1boolean

Second test, evaluated only when condition0 is false.

action1any

Value of the cond when condition1 is true.

...any

Any further condition and action pairs, in that order.

default-actionany

Value of the cond when every condition is false. It is required: a cond without one fails the command with error 4 (parameter error).

Returns
any
Introduced
5.6.0
Example

Classify float bin “price” (a book list price) into string bands aligned with the bookstore example on the path expressions overview: at least 20 is “premium”, at least 12 is “mid”, at least 10 (the top-level “expensive” threshold in that example) is “standard”, otherwise “deal”.

String exp = "when ($.price >= 20.0 => 'premium', "
+ "$.price >= 12.0 => 'mid', "
+ "$.price >= 10.0 => 'standard', "
+ "default => 'deal')";

def

def(name, value)
Description

Binds a variable name to the value of an expression for the scope of a sibling let. The body of the let reads the binding with var. One or more def operands precede the final scoped expression; they are not valid as a stand-alone top-level expression outside let.

Arguments
NameTypeDescription
namestring literal

Name the binding is read by. It is fixed when the expression is built, and reusing a name already in scope is rejected.

valueany

Expression bound to name. It can read bindings defined earlier in the same let but not later ones, and it is not evaluated at all if the body never reads it.

Returns
any
Introduced
5.6.0
Example

Inside a let, bind float bin price to list_price and the constant 12.0 to mid_floor, then require list_price >= mid_floor (aligned with mid-tier list prices in the bookstore example). This pattern shows two def bindings before the body.

String exp = "let (list_price = $.price, mid_floor = 12.0) "
+ "then (${list_price} >= ${mid_floor})";

let

let(def(...), def(...), ..., expr)
Description

Introduces a local scope: one or more def bindings followed by a final body expression. The body may use var to read those names. The value of the whole let is the value of the body; bindings are not visible outside this let. Use this when an expensive or bulky sub-expression should be evaluated once and reused.

Arguments
NameTypeDescription
def(...)any

First binding, written as a def. At least one is required.

def(...)any

Second binding, which can read the first with var.

...any

Any further bindings, each able to read the ones before it.

exprany

Body of the scope, and the value of the whole let. It reads the bindings with var; they are not visible outside.

Returns
any
Introduced
5.6.0
Example

Bind float bin price to list_price, then match records where that price is either below the top-level expensive threshold (10) or above a premium cutoff (20), reusing the bound value twice (see the bookstore example).

String exp = "let (list_price = $.price) "
+ "then (${list_price} < 10.0 or ${list_price} > 20.0)";

unknown

unknown()
Description

Produces the special unknown trilean. Meaning depends on where the expression runs. In a cond used for an expression index, the default branch is often unknown() so the index stays sparse: only rows whose condition is true produce an index key; all others yield unknown and are skipped. In an operation expression (read or write inside operate), a result of unknown fails that sub-operation with error 26 (not applicable); EXP_READ_EVAL_NO_FAIL / EXP_WRITE_EVAL_NO_FAIL let later operations in the same operate call continue. For boolean filters (single-record policies, queries, and XDR shipping filters), only true selects or ships the record; false and unknown do not. During the metadata-only phase of filter evaluation, needing bin data can yield unknown and trigger a storage-data phase (see the execution model); avoid writing filters that unnecessarily depend on that if you want a metadata-only path. If a cond test evaluates to unknown, the whole cond becomes unknown and later tests are skipped. Failed arithmetic (for example division by zero) also yields unknown. Except for logic operators, when any operand evaluates to unknown, the parent expression does too. The value propagates up the expression tree. The common exception is or: if at least one boolean child is true, or resolves to true even when other children are unknown. See Disjunction (or) in the expressions overview.

Returns
unknown
Introduced
5.6.0
Example

Sparse expression index pattern from the tutorial: if the customer is an adult in a target country, return age as the indexed value; otherwise return unknown() so the record is not indexed.

String exp = "when ($.age >= 18 and ($.country == 'Australia'"
+ " or $.country == 'Canada' or $.country == 'Botswana')"
+ " => $.age, default => unknown)";

var

var(name)
Description

Returns the value bound to name by a def: an earlier one in the same let, or one in a let that encloses it. It does not read bins: a name no def in scope binds fails the command with error 4, even when a bin has that name.

Arguments
NameTypeDescription
namestring literal

Name of a binding in scope, as given to def. A name with no binding in scope fails the command with error 4 (parameter error).

Returns
any
Introduced
5.6.0
Example

Inside a let, bind float bin price once, then use var(“list_price”) twice to test 10 < list_price < 13 (strict between the bookstore expensive threshold and a mid-tier upper bound).

String exp = "let (list_price = $.price) "
+ "then (10.0 < ${list_price} and ${list_price} < 13.0)";