Skip to content

Operation 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 use operation expressions to read and write computed bin values server-side without a read-modify-write round trip.

Operation expressions as the name suggests are used in an operation - either to read from bins or write to a bin. Specifically they are used in read and write methods of ExpOperation.

The basic computational model of operate, where operation expressions are used, remains the same: A series of read or write commands are performed in a given sequence on a single record. What is new is that a read command can be an expression involving zero or more bins. Also, a write command can get the value from an expression (enabling, for example, use of cross-bin data with conditional logic) instead of a simple constant to update a bin.

A read with operation expression can also use an arbitrary name for the “computed bin” similar to the “as” keyword in the SQL statement SELECT expr AS bin.

The pattern for coding an Operation Expression is:

  1. Define Expression to read or write the bins.
  2. Use Expression object in ExpOperation.read or .write method that returns an Operation.
  3. Use “expression operations” in any API call that takes an operation list.

This is illustrated below.

// operate expression with write
// 1. Define Expression to write the bin with.
// if (age > 65 && comorbidities) {risk = "high";}
// else {risk = "normal";}
Expression writeExp = Exp.build(
Exp.cond(
Exp.and(
Exp.gt(
Exp.intBin("age"), Exp.val(65)),
Exp.boolBin("comorbidities")),
Exp.val("high"),
Exp.val("normal")));
// 2. Use Expression object in ExpOperation.write method.
Operation writeExpOp = ExpOperation.write("risk",
writeExp, // evaluates bin value to update
ExpWriteFlags.DEFAULT);
// operate expression with read
// 1. Define Expression to read bins.
// read "yes" if (risk == "high" or worktype == "frontline") else "no"
// as a computed bin "eligible"
Expression readExp = Exp.build(
Exp.cond(
Exp.or(
Exp.eq(
Exp.stringBin("risk"), Exp.val("high")),
Exp.eq(
Exp.stringBin("worktype"), Exp.val("frontline"))),
Exp.val("yes"),
Exp.val("no")));
// 2. Use Expression object in ExpOperation.read method.
Operation readExpOp = ExpOperation.read("eligible", // named "computed bin"
readExp, // evaluates value to return
ExpReadFlags.DEFAULT);
// 3. Use "expression operations" in any API call that takes an operation list.
Record record = Client.operate(WritePolicy policy, Key key, Operation writeExpOp, Operation readExpOp);

Note that the order of operations is important. The readExp relies on the risk bin which gets written in the writeExp, so the writeExp must come first.

With the Developer SDK, the write and read operation expressions above are AEL text passed to .upsertFrom() and .selectFrom():

DataSet people = DataSet.of(NAMESPACE, SET_NAME);
Record record = session.upsert(people.id(userId))
// write: same condition as writeExp above
.bin("risk").upsertFrom(
"when ($.age > 65 and $.comorbidities == true => 'high', default => 'normal')")
// read: same condition as readExp above, as a computed "eligible" bin
.bin("eligible").selectFrom(
"when ($.risk == 'high' or $.worktype == 'frontline' => 'yes', default => 'no')")
.execute()
.getFirstRecord();

Using expression operations vs R-M-W or UDFs

Aerospike developers have multiple ways to perform a record oriented read-write logic.

  1. Read record data to the client, modify, and write back (“R-M-W”).
  2. Create a UDF for the logic and invoke it on the record.
  3. Use expression operations in a multi-op request.

For read-write transactions, fetching the data to the client and writing back is expensive and requires special care to ensure read-write isolation. Lua UDFs can be difficult to implement, less flexible to change, and can be slower. So it is generally beneficial to use expression operations when possible.

Here is a suggested decision process:

  1. Use expression operations. However if expression operations cannot be used because the task, for example, requires unsupported features such as iterators and loops, then:
  2. Use client-side Read-Modify-Write (R-M-W) with version check if amount of data transfer as well as possibility of conflict due to concurrency is limited. Otherwise:
  3. Use UDFs if Lua server side programming model and performance meet the needs. Otherwise must use 2.

Note, Aerospike provides many ways to implement a given data task on one or multiple records. To determine the optimal way for a given task, one should consider and evaluate the options available including the various execution modes (synchronous, asynchronous, background, etc).

Next

Continue to the full operation expressions code example.