Skip to content

Expressions - C#

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Jump to the Code block for a combined complete example.

This page describes how to use expressions in single record commands.

Aerospike expressions are a strongly typed, functional, domain-specific language for manipulating and comparing bins and record metadata.

For expression usage within multi-record requests, see Batch operations and Queries.

Setup

The examples on this page use the following setup and record structure to illustrate the use of expressions in single record commands.

using Aerospike.Client;
// Define host configuration
Host config = new Host("127.0.0.1", 3000);
// Establishes a connection to the server
AerospikeClient client = new AerospikeClient(null, config);
// Creates a key with the namespace "sandbox", set "ufodata", and user key 5001
Key key = new Key("sandbox", "ufodata", 5001);

The record structure:

+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+
| PK | occurred | reported | posted | report | location |
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+
| 5001 | 20220531 | 20220601 | 20220601 | MAP('{"shape":["circle", "flash", "disc"], "summary":"Large flying disc flashed in the sky above the student union. Craziest thing I've ever seen!", "city":"Ann Arbor", "state":"Michigan", "duration":"5 minutes"}') | GeoJSON('{"type":"Point","coordinates":[42.2808,83.743]}') |
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+

Filter expressions

Record filtering expressions select records that satisfy a boolean expression and work with all single record commands (reads, writes, operations, and record UDFs), batch reads, and queries. Filters are only executed when a record exists. Filters are not executed when a record is created or is not found.

Read

When using a filter expression on a read command, the expression is defined within the read policy.

The following example creates a filter expression that checks the length of the shape list in the report map and only returns if there are more than two shapes.

// Create the policy
Policy policy = new Policy();
// Build the expression
policy.filterExp = Exp.Build(
Exp.GT(
ListExp.Size(
MapExp.GetByKey(MapReturnType.VALUE, Exp.Type.LIST, Exp.Val("shape"), Exp.MapBin("report"))
),
Exp.Val(2)
)
);
// Read the record
Record record = client.Get(policy, key);
// Do something
Console.WriteLine("Record: {0}", record.ToString().Split("bins:")[1]);
// Close the connection to the server
client.Close();

Write

When using a filter expression on a write command, the expression is defined within the write policy.

The following example creates a filter expression that checks if occurred is later than 20211231 and posted exists. If the filter returns true, a recent key with the value true will be added to the report map.

// Create the policy
WritePolicy writePolicy = new WritePolicy();
// Build the expression
writePolicy.filterExp = Exp.Build(
Exp.And(
Exp.GT(Exp.IntBin("occurred"), Exp.Val(20211231)),
Exp.BinExists("posted")
)
);
// Update the record
client.Operate(writePolicy, key,
MapOperation.Put(MapPolicy.Default, "report", Value.Get("recent"), Value.Get(true))
);
// Close the connection to the server
client.Close();

Operation expressions

Operation expressions are bin operations that atomically compute a value using information in the record or from data supplied by the expression itself.

The result is either returned to the client, in a read expression, or written to a specified bin, in a write expression.

You can define a record filter expression in the write policy of the operate method to determine the execution of a bin operation using an operation expression.

Variables, conditionals, and unknown values

Exp.Let evaluates definitions created with Exp.Def and makes them available through Exp.Var. Variable names must be unique within the Let. Exp.Cond evaluates condition/action pairs in order and runs only the action for the first true condition. The final argument is a required default action.

Exp.Unknown() deliberately produces the unknown value. Unknown is not the same as nil: it signals “no answer,” and by default it fails the operation with ResultCode.OP_NOT_APPLICABLE. Combined with the no-fail flags described below, it is how you express “leave this bin alone when the data does not qualify.”

The following expression adds a bonus to a non-negative score and returns unknown for a negative one. Exp.Let and Exp.Cond require server version 5.6 or later.

// Returns score + 5, or unknown when score is negative.
private static readonly Expression BonusScore = Exp.Build(
Exp.Let(
Exp.Def("current", Exp.IntBin("score")),
Exp.Cond(
Exp.GE(Exp.Var("current"), Exp.Val(0)),
Exp.Add(Exp.Var("current"), Exp.Val(5)),
Exp.Unknown())));

Read and write flags

Both ExpOperation.Read and ExpOperation.Write take a flags argument, and both default to failing the entire Operate() call when the expression resolves to unknown or hits a type error. The EVAL_NO_FAIL flag changes that. On a read, the operation returns no value for that expression instead of throwing. On a write, the operation becomes a no-op and the target bin is left as it was.

Write flags additionally control bin-level behavior:

ExpWriteFlagsBehavior
CREATE_ONLYFails with BIN_EXISTS_ERROR if the bin already exists.
UPDATE_ONLYFails with BIN_NOT_FOUND if the bin does not exist.
ALLOW_DELETEA nil result deletes the bin instead of failing.
POLICY_NO_FAILTurns the three violations above into no-ops. Does not affect expression errors.
EVAL_NO_FAILTurns expression errors into no-ops. Does not affect the policy violations above.

POLICY_NO_FAIL and EVAL_NO_FAIL cover different failures, so suppressing both requires both flags. Combine them with the bitwise OR operator.

client.Put(writePolicy, key, new Bin("score", 10));
Record result = client.Operate(writePolicy, key,
// Negative score: the write is skipped and the "bonus" bin is left untouched.
ExpOperation.Write("bonus", BonusScore, ExpWriteFlags.EVAL_NO_FAIL),
// Negative score: this throws OP_NOT_APPLICABLE and fails the whole command.
ExpOperation.Read("strict", BonusScore, ExpReadFlags.DEFAULT),
// Negative score: this returns no value and the command continues.
ExpOperation.Read("tolerant", BonusScore, ExpReadFlags.EVAL_NO_FAIL));
Console.WriteLine($"Bonus score: {result.GetValue("tolerant")}");

Read

The read expression operation computes an expression, and returns that value. A defined name in the operation can be used as the computed bin name when retrieving results.

The following example takes the Read filter expression example from above and changes the scenario slightly. This command computes the length of the shape list in the report map and returns the value in a computed bin called numShapes.

// Build the expression
Expression exp = Exp.Build(
ListExp.Size(
MapExp.GetByKey(MapReturnType.VALUE, Exp.Type.LIST, Exp.Val("shape"), Exp.MapBin("report"))
)
);
// Read the record
Record record = client.Operate(null, key,
ExpOperation.Read("numShapes", exp, ExpReadFlags.DEFAULT)
);
// Do something
Console.WriteLine("Record: {0}", record.ToString().Split("bins:")[1]);
// Close the connection to the server
client.Close();

Write

The write expression operation computes an expression and writes that value to a bin.

The following example takes the Write filter expression example from above and changes the scenario slightly. Using the same criteria to compute a recent value, reported bin value and posted bin exists, this command updates the report map with the recent value, true or false.

// Build the expression
Expression exp = Exp.Build(
MapExp.Put(MapPolicy.Default, Exp.Val("recent"),
Exp.And(
Exp.GT(Exp.IntBin("occurred"), Exp.Val(20211231)),
Exp.BinExists("posted")
),
Exp.MapBin("report")
)
);
// Update the record
client.Operate(null, key, ExpOperation.Write("report", exp, ExpWriteFlags.DEFAULT));
// Close the connection to the server
client.Close();

Code block

Expand this section for a single code block to create a Operation Expression
using Aerospike.Client;
// Define host configuration
Host config = new Host("127.0.0.1", 3000);
// Establishes a connection to the server
AerospikeClient client = new AerospikeClient(null, config);
// Creates a key with the namespace "sandbox", set "ufodata", and user key 5001
Key key = new Key("sandbox", "ufodata", 5001);
// Build the expression
Expression exp = Exp.Build(
MapExp.Put(MapPolicy.Default, Exp.Val("recent"),
Exp.And(
Exp.GT(Exp.IntBin("occurred"), Exp.Val(20211231)),
Exp.BinExists("posted")
),
Exp.MapBin("report")
)
);
// Update the record
client.Operate(null, key, ExpOperation.Write("report", exp, ExpWriteFlags.DEFAULT));
// Close the connection to the server
client.Close();

History of expressions in Aerospike Database

  • Secondary index expressions introduced in Database 8.1.0
  • Operation expressions introduced in Database 5.6.0
  • XDR filter expressions introduced in Database 5.3.0
  • Record filter expressions introduced in Database 5.2.0