# Expressions - Node.js

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/node/usage/multi/batch) and [Queries](https://aerospike.com/docs/develop/client/node/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.

```js
const Aerospike = await import("aerospike");

const op = Aerospike.operations;

const map = Aerospike.maps;

const list = Aerospike.lists;

const exp = Aerospike.exp;

// Set hosts to your server's address and port

const config = { hosts: "YOUR_HOST_ADDRESS:YOUR_PORT" };

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

const key = new Aerospike.Key("sandbox", "ufodata", 5001);

// Establishes a connection to the server

const client = await Aerospike.connect(config);
```

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 the command is ignored.
:::

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

```js
// Create the policy and filterExpression

const readPolicy = new Aerospike.ReadPolicy({

  filterExpression: exp.gt(

    exp.lists.size(

      exp.maps.getByKey(

        exp.binMap("report"),

        exp.str("shape"),

        exp.type.LIST,

        map.returnType.VALUE,

      ),

    ),

    exp.int(2),

  ),

});

// Read the record

const record = await client.get(key, readPolicy);
```

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

```js
// Create the policy and filterExpression

const writePolicy = new Aerospike.WritePolicy({

  filterExpression: exp.and(

    exp.gt(exp.binInt("occurred"), exp.int(20211231)),

    exp.binExists("posted"),

  ),

});

// Create the ops

const ops = [map.put("report", "recent", true)];

// Metadata may be passed; use null to send no metadata

const metadata = null;

// Update the record

await client.operate(key, ops, metadata, writePolicy);
```

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

```js
// Build the expression

const expr = exp.lists.size(

  exp.maps.getByKey(

    exp.binMap("report"),

    exp.str("shape"),

    exp.type.LIST,

    map.returnType.VALUE,

  ),

);

// Create the ops

const ops = [exp.operations.read("numShapes", expr, 0)];

// Read the record

const record = await client.operate(key, ops);
```

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

```js
// Build the expression

const expr = exp.maps.put(

  exp.binMap("report"),

  exp.and(

    exp.gt(exp.binInt("occurred"), exp.int(20211231)),

    exp.binExists("posted"),

  ),

  exp.str("recent"),

);

// Create the ops

const ops = [exp.operations.write("report", expr, 0)];

// Update the record

await client.operate(key, ops);
```

## Code block

Expand this section for a single code block to create a Expression operation

```js
const Aerospike = await import("aerospike");

const op = Aerospike.operations;

const map = Aerospike.maps;

const list = Aerospike.lists;

const exp = Aerospike.exp;

// Set hosts to your server's address and port

const config = { hosts: "YOUR_HOST_ADDRESS:YOUR_PORT" };

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

const key = new Aerospike.Key("sandbox", "ufodata", 5001);

// Establishes a connection to the server

const client = await Aerospike.connect(config);

// Build the expression

const expr = exp.maps.put(

  exp.binMap("report"),

  exp.and(

    exp.gt(exp.binInt("occurred"), exp.int(20211231)),

    exp.binExists("posted"),

  ),

  exp.str("recent"),

);

// Create the ops

const ops = [exp.operations.write("report", expr, 0)];

// Update the record

await client.operate(key, ops);

await 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