# Expressions - Java

Jump to the [Code block](#code-block) for a combined complete example.

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

[Aerospike expressions](https://aerospike.com/docs/develop/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 the [Batch operations](https://aerospike.com/docs/develop/client/java/usage/multi/batch) and [Queries](https://aerospike.com/docs/develop/client/java/usage/multi/queries/primary) pages.

## Setup

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

```java
import com.aerospike.client.AerospikeClient;

import com.aerospike.client.policy.Policy;

import com.aerospike.client.policy.WritePolicy;

import com.aerospike.client.Bin;

import com.aerospike.client.Key;

import com.aerospike.client.Record;

import com.aerospike.client.Value;

import com.aerospike.client.Operation;

import com.aerospike.client.cdt.MapPolicy;

import com.aerospike.client.cdt.MapOperation;

import com.aerospike.client.cdt.MapReturnType;

import com.aerospike.client.exp.Exp;

import com.aerospike.client.exp.ExpOperation;

import com.aerospike.client.exp.ExpWriteFlags;

import com.aerospike.client.exp.ExpReadFlags;

import com.aerospike.client.exp.Expression;

import com.aerospike.client.exp.ListExp;

import com.aerospike.client.exp.MapExp;

// Establishes a connection to the server

AerospikeClient client = new AerospikeClient("127.0.0.1", 3000);

// Creates a key with the namespace "sandbox", set "ufodata", and user key 5001

Key key = new Key("sandbox", "ufodata", 5001);
```

The record structure:

```plaintext
+------+----------+----------+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------+

| 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](https://aerospike.com/docs/develop/expressions/#record-filtering-with-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.

::: note
When a filter evaluates to `false` on the server, a record is filtered out from the operation, and the Java client returns `null` by default. The `failOnFilteredOut` policy can be set to `true` to receive an exception instead of a `null` return value.
:::

### 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.

```java
// 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

System.out.format("Record: %s\\n", record.bins);

// 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.

```java
// 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](https://aerospike.com/docs/develop/expressions#operation-expressions) are bin operations that atomically compute a value from information within the record or provided by the expression. 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](https://aerospike.com/docs/develop/expressions/#record-filtering-with-expressions) in the write policy of the `operate` method to determine the execution of a [bin operation](https://aerospike.com/docs/develop/client/java/usage/atomic/multi) using an operation expression.

### Read

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

The following example takes the [Read](#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 synthetic bin called `numShapes`.

```java
// 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

System.out.format("Record: %s\\n", record.bins);

// 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](#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`.

```java
// 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

```java
import com.aerospike.client.AerospikeClient;

import com.aerospike.client.policy.Policy;

import com.aerospike.client.policy.WritePolicy;

import com.aerospike.client.Bin;

import com.aerospike.client.Key;

import com.aerospike.client.Record;

import com.aerospike.client.Value;

import com.aerospike.client.Operation;

import com.aerospike.client.cdt.MapPolicy;

import com.aerospike.client.cdt.MapOperation;

import com.aerospike.client.cdt.MapReturnType;

import com.aerospike.client.exp.Exp;

import com.aerospike.client.exp.ExpOperation;

import com.aerospike.client.exp.ExpWriteFlags;

import com.aerospike.client.exp.ExpReadFlags;

import com.aerospike.client.exp.Expression;

import com.aerospike.client.exp.ListExp;

import com.aerospike.client.exp.MapExp;

// Establishes a connection to the server

AerospikeClient client = new AerospikeClient("127.0.0.1", 3000);

// 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