Skip to content

Declare and control-flow

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.

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
NameType
condition0 boolean-expr
action0 expr
condition1 boolean-expr
action1 expr
... expr
default-action expr
Returns
expr
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”.

Expression writeExp = Exp.build(
Exp.cond(
Exp.ge(Exp.floatBin("price"), Exp.val(20.0)), Exp.val("premium"),
Exp.ge(Exp.floatBin("price"), Exp.val(12.0)), Exp.val("mid"),
Exp.ge(Exp.floatBin("price"), Exp.val(10.0)), Exp.val("standard"),
Exp.val("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
NameType
name string-value
value expr
Returns
expr
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.

Expression exp = Exp.build(
Exp.let(
Exp.def("list_price", Exp.floatBin("price")),
Exp.def("mid_floor", Exp.val(12.0)),
Exp.ge(Exp.var("list_price"), Exp.var("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
NameType
def(...) def-expr
def(...) def-expr
... def-exprs
expr expr
Returns
expr
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).

Expression exp = Exp.build(
Exp.let(
Exp.def("list_price", Exp.floatBin("price")),
Exp.or(
Exp.lt(Exp.var("list_price"), Exp.val(10.0)),
Exp.gt(Exp.var("list_price"), Exp.val(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.

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.

Expression filterExp = Exp.build(
Exp.cond(
Exp.and(
Exp.ge(Exp.intBin("age"), Exp.val(18)),
Exp.or(
Exp.eq(Exp.stringBin("country"), Exp.val("Australia")),
Exp.eq(Exp.stringBin("country"), Exp.val("Canada")),
Exp.eq(Exp.stringBin("country"), Exp.val("Botswana")))),
Exp.intBin("age"),
Exp.unknown()));

var

var(name)
Description

Reads a value bound by def inside the same let. The name must match a preceding def in that let. var is only meaningful within the body of that let; it does not access bins or outer scope by itself.

Arguments
NameType
name string-value
Returns
expr
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).

Expression exp = Exp.build(
Exp.let(
Exp.def("list_price", Exp.floatBin("price")),
Exp.and(
Exp.lt(Exp.val(10.0), Exp.var("list_price")),
Exp.lt(Exp.var("list_price"), Exp.val(13.0)))));
Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?