> Filter operators, AND/OR logic, sorting, and pagination for SDK queries

# Filtering & Sorting

These options work the same in the server client and the hooks.

## Filter structure

```typescript filename="example.ts"
filter: {
  query: [{
    condition: {
      field: 'name',
      operator: 'equal',
      value: 'Acme Corp',
    },
  }],
  sortby: [{ field: 'created_at', order: 'desc' }],
}
```

## Operators

### String

| Operator     | Description                          | Example value |
| ------------ | ------------------------------------ | ------------- |
| `equal`      | Exact match                          | `"value"`     |
| `notEqual`   | Not equal                            | `"value"`     |
| `like`       | Pattern match (case-sensitive)       | `"%search%"`  |
| `ilike`      | Pattern match (case-insensitive)     | `"%search%"`  |
| `notLike`    | Not pattern match                    | `"%exclude%"` |
| `notiLike`   | Not pattern match (case-insensitive) | `"%exclude%"` |
| `startsWith` | Starts with                          | `"prefix"`    |
| `endsWith`   | Ends with                            | `"suffix"`    |

### Number & date

| Operator             | Description           |
| -------------------- | --------------------- |
| `equal`              | Equal to              |
| `notEqual`           | Not equal to          |
| `greaterThan`        | Greater than          |
| `lessThan`           | Less than             |
| `greaterThanOrEqual` | Greater than or equal |
| `lessThanOrEqual`    | Less than or equal    |

### Null & empty

These operators need no `value`.

| Operator     | Description       |
| ------------ | ----------------- |
| `isNull`     | Field is null     |
| `isNotNull`  | Field is not null |
| `isEmpty`    | Empty string      |
| `isNotEmpty` | Not empty         |

### Boolean

| Operator  | Description    |
| --------- | -------------- |
| `isTrue`  | Field is true  |
| `isFalse` | Field is false |

### List

Use `values` instead of `value`:

```typescript filename="example.ts"
condition: {
  field: 'status',
  operator: 'in',
  values: ['paid', 'pending'],
}
```

| Operator | Description       |
| -------- | ----------------- |
| `in`     | Value in list     |
| `notIn`  | Value not in list |

## AND / OR

All conditions must match:

```typescript filename="example.ts"
filter: {
  query: [{
    and: [
      { condition: { field: 'amount_net', operator: 'greaterThan', value: '1000' } },
      { condition: { field: 'status', operator: 'equal', value: 'paid' } },
    ],
  }],
}
```

Any condition can match:

```typescript filename="example.ts"
filter: {
  query: [{
    or: [
      { condition: { field: 'name', operator: 'ilike', value: '%acme%' } },
      { condition: { field: 'name', operator: 'ilike', value: '%corp%' } },
    ],
  }],
}
```

## Sorting

Multiple sort fields apply in order, primary first.

```typescript filename="example.ts"
filter: {
  sortby: [
    { field: 'created_at', order: 'desc' },
    { field: 'name', order: 'asc' },
  ],
}
```

## Pagination

```typescript filename="example.ts"
pagination: {
  page: 1,      // 1-indexed
  per_page: 20,
}
```

Every list response includes:

| Field            | Type      | Description                       |
| ---------------- | --------- | --------------------------------- |
| `total`          | `number`  | Total number of matching entities |
| `current_page`   | `number`  | Current page number               |
| `per_page`       | `number`  | Items per page                    |
| `last_page`      | `number`  | Last available page number        |
| `has_more_pages` | `boolean` | Whether more pages exist          |

Next: [Mutations](/data/mutations)
