# Expressions and SDK code

The expression you build in Aerospike Voyager is the same string your application ships with. There is no rewrite step when moving from prototype to production. The filter you build on day one is the same filter your production code uses.

This is the core portability promise of Voyager’s expression support: build, test, and refine your filter visually, then copy the expression string into any Aerospike SDK.

## From visual filter to expression to SDK code

Here is a complete walkthrough showing how a visual filter becomes production code.

### Step 1: Build a visual filter

In the Filters tab, create two conditions:

1.  **age** `> greater than` **30**
2.  **country** `= equals` **US**

Set the combinator to **AND** and click **Apply**.

### Step 2: View the expression string

Click the **Expression** tab. Voyager displays the expression it generated:

```text
$.age > 30 and $.country == 'US'
```

 ![Filter panel Expression tab showing the generated expression string with a copy button](https://aerospike.com/docs/_astro/expression_tab.55zpDAzW_Z1gBNkG.png)

In Aerospike Expression Language, the `$` prefix denotes a bin reference. For example, `$.age > 30` filters records where the age bin exceeds 30. This is a valid Aerospike expression string; it is exactly what the cluster evaluates when filtering records.

For the complete operator list, see the [available operators](https://aerospike.com/docs/database/tools/voyager/guides/filtering-records#available-operators) in the filtering guide.

### Step 3: Copy the expression

Click the **Copy** button in the Expression tab to copy the expression string to your clipboard.

### Step 4: Use the expression in SDK code

Paste the expression into your application. In the new Java SDK, the AEL string is what the `.where(...)` clause accepts — the paste is literal, with no builder rewrite.

**Java:**

```java
import com.aerospike.client.sdk.Cluster;

import com.aerospike.client.sdk.ClusterDefinition;

import com.aerospike.client.sdk.DataSet;

import com.aerospike.client.sdk.RecordStream;

import com.aerospike.client.sdk.Session;

import com.aerospike.client.sdk.policy.Behavior;

public class FilterExample {

    public static void main(String[] args) {

        try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {

            Session session = cluster.createSession(Behavior.DEFAULT);

            DataSet users = DataSet.of("test", "sample_users");

            // Paste the expression copied from Voyager, unchanged

            try (RecordStream stream = session.query(users)

                    .where("$.age > 30 and $.country == 'US'")

                    .execute()) {

                stream.forEach(r -> {

                    if (r.isOk()) {

                        System.out.println(r.recordOrThrow());

                    }

                });

            }

        }

    }

}
```

**Python:**

```python
from aerospike_sdk import SyncClient

# Connect to the cluster

with SyncClient("localhost:3000") as client:

    # Paste the expression copied from Voyager, unchanged

    stream = (

        client.query(namespace="test", set_name="sample_users")

        .where("$.age > 30 and $.country == 'US'")

        .execute()

    )

    for row in stream:

        if row.record:

            print(row.record.bins)
```

## SDK code snippets for record creation

When you create a record in Voyager using the **Add new record** dialog, the **Code snippets (Experimental)** section generates equivalent SDK code in five languages: Golang, Java, JavaScript, Python, and C++ (in that order).

 ![Add new record dialog with the Code snippets (Experimental) section expanded, showing language tabs for Golang, Java, JavaScript, Python, and C++](https://aerospike.com/docs/_astro/add_record_code_snippets.BeZfyT9A_Zuay0j.png)

Expand the section in the dialog to view the generated snippet, then copy it into your application. This is useful when you prototype a data model in Voyager and want to reproduce the same records programmatically.

## CDT expressions in SDK code

Expressions that access list and map bins ([CDT](https://aerospike.com/docs/database/learn/architecture/data-storage/data-model) operations) translate to SDK code the same way. Here is an example that filters records where the first element of a list bin equals a specific value.

**Expression in Voyager:**

```text
$.roles.[0] == 'admin'
```

**Java:**

```java
RecordStream stream = session.query(users)

    .where("$.roles.[0] == 'admin'")

    .execute();
```

**Python:**

```python
from aerospike_sdk import SyncClient

with SyncClient("localhost:3000") as client:

    stream = (

        client.query(namespace="test", set_name="sample_users")

        .where("$.roles.[0] == 'admin'")

        .execute()

    )

    for row in stream:

        if row.record:

            print(row.record.bins)
```

## Copying expressions

To copy an expression string from Voyager:

1.  Open the **Expression** tab in the filter panel.
2.  Click the **Copy** button (clipboard icon) in the top-right corner of the editor.

The full expression string is copied to your clipboard, ready to paste into your SDK code.

::: tip
If you built your filter in the Filters tab, switch to the Expression tab to see and copy the generated expression before moving to your code editor.
:::

## Related resources

-   [Filtering records](https://aerospike.com/docs/database/tools/voyager/guides/filtering-records): Full guide to both filter surfaces in Voyager.
-   [Available operators](https://aerospike.com/docs/database/tools/voyager/guides/filtering-records#available-operators): Complete table of visual builder operators.
-   [Aerospike Expression Language reference](https://aerospike.com/docs/develop/expressions): Full language specification.