Understanding expressions
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
This page is for developers using Aerospike client libraries. Complete Setup first. After reading this page, you can explain how Aerospike expressions are formed and how filter and operation expressions differ.
The examples on this page use plain, language-independent notation (similar in style to AEL) to focus on the underlying concepts before introducing client code. Concrete examples in Java, Python, Go, C#, Node.js, and Rust, with equivalent AEL text for Java and Python, begin in Syntax and coding patterns.
Defining expressions
An expression is a syntactic entity in a programming language that may be evaluated to determine its value. (Wikipedia)
In other words, an expression evaluates to (or returns) a value. Some simple examples of an expression would be:
57 + 32 > 1Expressions can have:
-
constants:
5, "horse", [1, 2, 3]
In this example, they are an integer, a string and a list of numbers
-
variables:
var x = pow(b, c) + d -
functions:
pow, mod, min -
and operators:
==, +, or
Expressions are composable. In other words, complex expressions can be formed from simpler expressions. For example:
1 + min(2, a + 2) < sqrt(b)An expression is not an assignment: An expression does not assign a value to a variable, but simply evaluates to a value which may be used in an assignment statement that assigns the value to a variable.
Expressions in Aerospike
This section provides a higher level view of the capabilities and workings of expressions in Aerospike. The subsequent sections will drill down into the details.
Evaluation context
Expressions are evaluated on the server for filtering conditions, reading
and writing to bins, and configuring XDR replication. Therefore, an
expression only works on server data entities such as the metadata and
record data, and uses any constants that the client may provide. When
used from the client library, expressions are created on the client and
sent to the server in an API operation. Before sending, the client
object format of an expression is converted to a wire format using the
build operation.
Components and scope
- An expression is a combination of one or more constants, variables, functions, and operators that the programming language interprets … and computes to produce another value.* (Wikipedia)
In Aerospike, expressions use bins, metadata functions and API calls, and values that are strongly typed as boolean, integer, float, string, list, map, blob, GeoJSON, or HyperLogLog. A host of arithmetic, logical, convenience, and API operations are available for these data.
See Expressions for the list of supported components.
Immutability of components
In Aerospike, an expression works on a transient copy, therefore evaluating an expression does not change the metadata or bins that are used in the expression.
For example, $.firstName + " " + $.lastName forms a result which joins the two bins but changes neither.
Use of variables
A variable can be defined to represent a sub-expression for syntactic clarity and efficiency. A variable is first defined and initialized by assigning it to an expression, and then used as a substitute for the expression. In the example below, a variable myvar is defined and used in an expression myexpr:
let( myvar = ($.a:INT + $.b) / min($.a, $.b), myexpr = ${myvar} +1 / ${myvar})then (${myexpr})Conditional evaluation
An expression can be conditionally evaluated with an if-then-else like construct. Note the else case is always required. For example:
let ( myexpr = when( $.cond_1 => $.expr_1, $.cond_2 => $.expr_2, default => $.default )then (...)Uses and types
Expressions are used in:
- selection conditions aka predicates (called Filter Expressions),
- operations (called Operation Expressions), and
- XDR’s shipping configuration (called XDR Filter Expressions).
The functionality of expressions is the same, although the context determines their use. For example, Filter and XDR Filter Expressions are boolean expressions, whereas Operation Expressions can evaluate to any supported type.
Only Filter and Operation Expressions can be used in the client library and therefore will be the focus of this tutorial. See Filtering XDR records with expressions for the details of XDR Filter Expressions.
AEL text authoring
Starting with Aerospike Database 8.2, Filter and Operation Expressions
can also be authored as readable Aerospike Expression Language (AEL) text
instead of a compiled Exp tree. The Developer SDK
(Java and Python) accepts AEL strings directly in its query and operation
builders: .where(...) for a filter expression, and .selectFrom(...) /
.upsertFrom(...) / .updateFrom(...) for an operation expression.
This tutorial primarily uses the classic Java client and the Exp.*
builder, with equivalent classic Python (exp.*), Go (Exp*), C#
(Exp.*), Node.js (exp.*), and Rust (aerospike::expressions::*)
examples alongside it, since that is the supported expression API for
those clients. The Rust client’s builder functions are free functions
rather than a fluent builder — for example, eq(int_bin("a"), int_val(1)) instead of Exp.eq(Exp.intBin("a"), Exp.val(1)). Each
filter and operation-expression example also shows the equivalent AEL
text and how it would be authored with the Developer SDK (Java and
Python only — Go, C#, Node.js, and Rust continue to use their respective
expression builders). See the
AEL overview and
AEL reference for the
full grammar.
Benefits of expressions
Here are some key benefits and capabilities that expressions enable:
-
Capabilities in expressions include:
- variables for syntactic clarity and efficiency,
- conditional evaluation,
- access to metadata and bin data, and
- access to powerful APIs and enhanced set of operators.
-
The enhanced filtering expressions allow records to be processed more efficiently by avoiding the need for potentially more expensive client or UDF based processing.
-
Reads and writes are now possible with Operation Expressions.
- in reads, this can eliminate the need to bring large amounts of data to the client with more precise ability to specify the data to be fetched.
- a bin can be updated with the results of an expression, which can eliminate having to read before update by allowing everything to happen on the server side in the same request including the read, processing for update, and update. This saves a round-trip and transfer of potentially large data. In a concurrent setting, this also avoids retries due to conflicts see the R-M-W pattern.
-
Multi-step operations that can build on each other’s results are now possible through operation expressions.
Next
Continue to Syntax and coding patterns.