# Filtering

Source: https://neondeerdata.com/docs/api/lookup-tables/filtering/

Filter rows with equality, membership, and AND/OR conditions.

## Filter format

This format applies to lookup-table rows. Duplicate-set filters and scan selections have their own schemas; see [Duplicate Detection](https://neondeerdata.com/docs/api/duplicate-detection/).

Send a filter in the JSON body of [Query rows](https://neondeerdata.com/docs/api/lookup-tables/query-rows/). GET row requests do not accept filter parameters.

| Operator   | Matches                                                  |
| ---------- | -------------------------------------------------------- |
| `eq`       | A value equal to the supplied value after normalization. |
| `in`       | Any value in a nonempty list.                            |
| `and`      | Every condition in a group.                              |
| `or`       | Any condition in a group.                                |
| `eq: null` | An empty cell.                                           |

For example, match an account domain:

```json
{ "filter": { "field": "account_domain", "eq": "acme.example.com" } }

```

Use the field's `key`, not its display label, and send the correct JSON type. Text equality ignores case; it does not match partial text. See [Value formats](https://neondeerdata.com/docs/api/lookup-tables/concepts/#value-formats) for numbers, booleans, dates, and other types.

## Choose a field

You can filter any readable field marked `filterable: true`. **Lookup key** does not need to be enabled. While a table is being prepared, fields can report `filterable: false`; wait and fetch the schema again.

Filtering and uniqueness are separate. A field with `unique: false` can match several rows. A nonempty value on a field with `unique: true` matches at most one row. No matches returns `200` and `data: []`.

For example, a non-unique region field can match several account-owner rows:

```json
{ "filter": { "field": "region", "eq": "EMEA" } }

```

The key must be allowed to read every field used in a filter. A filtered field does not have to appear in the response's `fields` selection; that list only controls what is returned.

## Match several values

Use `in` for any value in a nonempty list:

```json
{
  "filter": {
    "field": "account_domain",
    "in": ["acme.example.com", "blue-lake.example.com"]
  },
  "fields": ["account_domain", "owner_email"]
}

```

Results use row-ID order, not the order of values in the list. Follow `next_cursor` for more results.

## Combine conditions

Use `and` when all conditions must match, or `or` when any can match. Each group must be nonempty. Each condition contains `field` and either `eq` or `in`, never both.

This query combines account-domain matches with an owner-email condition. Both fields must be readable and filterable:

```json
{
  "filter": {
    "and": [
      {
        "or": [
          { "field": "account_domain", "eq": "acme.example.com" },
          { "field": "account_domain", "eq": "blue-lake.example.com" }
        ]
      },
      { "field": "owner_email", "eq": "dana.whitfield@example.com" }
    ]
  }
}

```

Use flat groups, an `and` of `or` groups, or an `or` of `and` groups. If a filter is too complex, simplify the nesting or split the query.

## Empty cells

Use `eq: null` to find empty cells:

```json
{ "filter": { "field": "account_domain", "eq": null } }

```

This can match several rows even on a unique field. It does not match `0`, `false`, or an empty string. Empty-string filters are rejected, and `null` cannot appear in an `in` list.

## Pagination

Keep the same filter structure, condition order, `in` value order, and segment settings when using a cursor. Continue until `next_cursor` is `null`, even after an empty page. Omitting `filter` reads all rows the key may read, with pagination.

See [Pagination](https://neondeerdata.com/docs/api/lookup-tables/pagination/) for cursor recovery and [Errors](https://neondeerdata.com/docs/api/errors/) for invalid filters and values.

## Unsupported filters

Lookup-row queries do not support range comparisons, contains, prefix, or suffix searches, regular expressions, fuzzy matching, NOT or not-equal conditions, or comparing one field with another. Read the relevant values and apply those comparisons in your application.

Rows are always returned in ascending ID order. Read all pages before applying a different sort in your application.

## Try a filter

The [API Playground](https://neondeerdata.com/docs/api/testing/) supports equality conditions combined with AND. To use `in`, OR, empty-cell filters, or pagination options, copy a sample and edit it in your application or API client.
