# Expressions - Python

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

## Setup

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

```python
import aerospike

from aerospike_helpers import expressions as exp

from aerospike_helpers.operations import expression_operations, map_operations, operations

# Define host configuration

config = {

    'hosts': [ ('127.0.0.1', 3000) ]

}

# Establishes a connection to the server

client = aerospike.client(config).connect()

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

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, the result returned depends on the operation. See the Python client [filter behavior](https://aerospike-python-client.readthedocs.io/en/latest/aerospike_helpers.expressions.html#filter-behavior) for more detail.
:::

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

```python
# Build the expression

expr = exp.GT(

    exp.ListSize(

        None,

        exp.MapGetByKey(None, aerospike.MAP_RETURN_VALUE, exp.ResultType.LIST, 'shape', exp.MapBin('report'))

    ),

    2).compile()

# Create the policy

policy = {'expressions': expr}

# Read the record

(key_, meta, bins) = client.get(key, policy=policy)

# Do something

print('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.

```python
# Build the expression

expr = exp.And(

        exp.GT(exp.IntBin('occurred'), 20211231),

        exp.BinExists('posted')).compile()

# Create the policy

policy = {'expressions': expr}

# Create map policy

map_policy = {'map_write_flags': aerospike.MAP_WRITE_FLAGS_DEFAULT}

# Create operations

ops = [map_operations.map_put('report', 'recent', True, map_policy)]

# Update the record

(key_, meta, bins) = client.operate(key, ops, policy=policy)

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

```python
# Build the expression

expr = exp.ListSize(

    None,

    exp.MapGetByKey(None, aerospike.MAP_RETURN_VALUE, exp.ResultType.LIST, 'shape', exp.MapBin('report'))).compile()

# Create operations

ops = [expression_operations.expression_read('numShapes', expr, aerospike.EXP_READ_DEFAULT)]

# Read the record

(keys_, meta, bins) = client.operate(key, ops)

# Do something

print('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`.

```python
# Build the expression

expr = exp.MapPut(None, None, 'recent',

    exp.And(

        exp.GT(exp.IntBin('occurred'), 20211231),

        exp.BinExists('posted')

    ),

    exp.MapBin('report')).compile()

# Create operations

ops = [expression_operations.expression_write('report', expr, aerospike.EXP_WRITE_DEFAULT)]

# Update the record

client.operate(key, ops)

# Close the connection to the server

client.close()
```

## Code block

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

```python
import aerospike

from aerospike_helpers import expressions as exp

from aerospike_helpers.operations import expression_operations, map_operations, operations

# Define host configuration

config = {

    'hosts': [ ('127.0.0.1', 3000) ]

}

# Establishes a connection to the server

client = aerospike.client(config).connect()

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

key = ('sandbox', 'ufodata', 5001)

# Build the expression

expr = exp.MapPut(None, None, 'recent',

    exp.And(

        exp.GT(exp.IntBin('occurred'), 20211231),

        exp.BinExists('posted')

    ),

    exp.MapBin('report')).compile()

# Create operations

ops = [expression_operations.expression_write('report', expr, aerospike.EXP_WRITE_DEFAULT)]

# Update the record

client.operate(key, ops)

# 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