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(condition0, action0, condition1, action1, ..., default-action)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.
| Name | Type |
|---|---|
condition0 | boolean-expr |
action0 | expr |
condition1 | boolean-expr |
action1 | expr |
... | expr |
default-action | expr |
expr 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")));from aerospike_helpers.expressions import Cond, FloatBin, GE, Val
write_exp = Cond( GE(FloatBin("price"), 20.0), Val("premium"), GE(FloatBin("price"), 12.0), Val("mid"), GE(FloatBin("price"), 10.0), Val("standard"), Val("deal"),).compile()as_exp_build(write_exp, as_exp_cond( as_exp_cmp_ge( as_exp_bin_float("price"), as_exp_float(20.0)), as_exp_str("premium"), as_exp_cmp_ge( as_exp_bin_float("price"), as_exp_float(12.0)), as_exp_str("mid"), as_exp_cmp_ge( as_exp_bin_float("price"), as_exp_float(10.0)), as_exp_str("standard"), as_exp_str("deal")));// Import path matches the Go client examples elsewhere on this doc site (/v6).// If you use the latest client line, switch to .../aerospike-client-go/v8 (API names unchanged).// Requires: import as "github.com/aerospike/aerospike-client-go/v6"writeExp := as.ExpCond( as.ExpGreaterEq(as.ExpFloatBin("price"), as.ExpFloatVal(20.0)), as.ExpStringVal("premium"), as.ExpGreaterEq(as.ExpFloatBin("price"), as.ExpFloatVal(12.0)), as.ExpStringVal("mid"), as.ExpGreaterEq(as.ExpFloatBin("price"), as.ExpFloatVal(10.0)), as.ExpStringVal("standard"), as.ExpStringVal("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")));const exp = Aerospike.exp
const writeExp = exp.cond( exp.ge(exp.binFloat('price'), exp.float(20.0)), exp.str('premium'), exp.ge(exp.binFloat('price'), exp.float(12.0)), exp.str('mid'), exp.ge(exp.binFloat('price'), exp.float(10.0)), exp.str('standard'), exp.str('deal'))def(name, value)| Name | Type |
|---|---|
name | string-value |
value | expr |
expr 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"))));from aerospike_helpers.expressions import Def, FloatBin, GE, Let, Val, Var
exp = Let( Def("list_price", FloatBin("price")), Def("mid_floor", Val(12.0)), GE(Var("list_price"), Var("mid_floor")),).compile()as_exp_build(predexp, as_exp_let( as_exp_def("list_price", as_exp_bin_float("price")), as_exp_def("mid_floor", as_exp_float(12.0)), as_exp_cmp_ge( as_exp_var("list_price"), as_exp_var("mid_floor"))));// Import path matches the Go client examples elsewhere on this doc site (/v6).// If you use the latest client line, switch to .../aerospike-client-go/v8 (API names unchanged).// Requires: import as "github.com/aerospike/aerospike-client-go/v6"exp := as.ExpLet( as.ExpDef("list_price", as.ExpFloatBin("price")), as.ExpDef("mid_floor", as.ExpFloatVal(12.0)), as.ExpGreaterEq(as.ExpVar("list_price"), as.ExpVar("mid_floor")))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"))));const exp = Aerospike.exp
const writeExp = exp.let( ...exp.def('list_price', exp.binFloat('price')), ...exp.def('mid_floor', exp.float(12.0)), exp.ge(exp.var('list_price'), exp.var('mid_floor')))let(def(...), def(...), ..., expr)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.
| Name | Type |
|---|---|
def(...) | def-expr |
def(...) | def-expr |
... | def-exprs |
expr | expr |
expr 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)))));from aerospike_helpers.expressions import Def, FloatBin, GT, Let, LT, Or, Val, Var
exp = Let( Def("list_price", FloatBin("price")), Or( LT(Var("list_price"), Val(10.0)), GT(Var("list_price"), Val(20.0)), ),).compile()as_exp_build(predexp, as_exp_let( as_exp_def("list_price", as_exp_bin_float("price")), as_exp_or( as_exp_cmp_lt(as_exp_var("list_price"), as_exp_float(10.0)), as_exp_cmp_gt(as_exp_var("list_price"), as_exp_float(20.0)))));// Import path matches the Go client examples elsewhere on this doc site (/v6).// If you use the latest client line, switch to .../aerospike-client-go/v8 (API names unchanged).// Requires: import as "github.com/aerospike/aerospike-client-go/v6"exp := as.ExpLet( as.ExpDef("list_price", as.ExpFloatBin("price")), as.ExpOr( as.ExpLess(as.ExpVar("list_price"), as.ExpFloatVal(10.0)), as.ExpGreater(as.ExpVar("list_price"), as.ExpFloatVal(20.0))))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)))));const exp = Aerospike.exp
const writeExp = exp.let( ...exp.def('list_price', exp.binFloat('price')), exp.or( exp.lt(exp.var('list_price'), exp.float(10.0)), exp.gt(exp.var('list_price'), exp.float(20.0))))unknown()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.
unknown 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()));from aerospike_helpers.expressions import ( And, Cond, Eq, GE, IntBin, Or, StrBin, Unknown,)
country_is_target = Or( Eq(StrBin("country"), "Australia"), Eq(StrBin("country"), "Canada"), Eq(StrBin("country"), "Botswana"),)
filter_exp = Cond( And(GE(IntBin("age"), 18), country_is_target), IntBin("age"), Unknown(),).compile()as_exp_build(filter_exp, as_exp_cond( as_exp_and( as_exp_cmp_ge( as_exp_bin_int("age"), as_exp_int(18)), as_exp_or( as_exp_cmp_eq(as_exp_bin_str("country"), as_exp_str("Australia")), as_exp_cmp_eq(as_exp_bin_str("country"), as_exp_str("Canada")), as_exp_cmp_eq(as_exp_bin_str("country"), as_exp_str("Botswana")))), as_exp_bin_int("age"), as_exp_unknown()));// Import path matches the Go client examples elsewhere on this doc site (/v6).// If you use the latest client line, switch to .../aerospike-client-go/v8 (API names unchanged).// Requires: import as "github.com/aerospike/aerospike-client-go/v6"filterExp := as.ExpCond( as.ExpAnd( as.ExpGreaterEq(as.ExpIntBin("age"), as.ExpIntVal(18)), as.ExpOr( as.ExpEq(as.ExpStringBin("country"), as.ExpStringVal("Australia")), as.ExpEq(as.ExpStringBin("country"), as.ExpStringVal("Canada")), as.ExpEq(as.ExpStringBin("country"), as.ExpStringVal("Botswana")), ), ), as.ExpIntBin("age"), as.ExpUnknown())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()));const exp = Aerospike.exp
const filterExp = exp.cond( exp.and( exp.ge(exp.binInt('age'), exp.int(18)), exp.or( exp.eq(exp.binStr('country'), exp.str('Australia')), exp.eq(exp.binStr('country'), exp.str('Canada')), exp.eq(exp.binStr('country'), exp.str('Botswana')))), exp.binInt('age'), exp.unknown())var(name)| Name | Type |
|---|---|
name | string-value |
expr 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)))));from aerospike_helpers.expressions import And, Def, FloatBin, Let, LT, Val, Var
exp = Let( Def("list_price", FloatBin("price")), And( LT(Val(10.0), Var("list_price")), LT(Var("list_price"), Val(13.0)), ),).compile()as_exp_build(predexp, as_exp_let( as_exp_def("list_price", as_exp_bin_float("price")), as_exp_and( as_exp_cmp_lt(as_exp_float(10.0), as_exp_var("list_price")), as_exp_cmp_lt(as_exp_var("list_price"), as_exp_float(13.0)))));// Import path matches the Go client examples elsewhere on this doc site (/v6).// If you use the latest client line, switch to .../aerospike-client-go/v8 (API names unchanged).// Requires: import as "github.com/aerospike/aerospike-client-go/v6"exp := as.ExpLet( as.ExpDef("list_price", as.ExpFloatBin("price")), as.ExpAnd( as.ExpLess(as.ExpFloatVal(10.0), as.ExpVar("list_price")), as.ExpLess(as.ExpVar("list_price"), as.ExpFloatVal(13.0))))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)))));const exp = Aerospike.exp
const writeExp = exp.let( ...exp.def('list_price', exp.binFloat('price')), exp.and( exp.lt(exp.float(10.0), exp.var('list_price')), exp.lt(exp.var('list_price'), exp.float(13.0))))