> ## Documentation Index
> Fetch the complete documentation index at: https://docs.joinrefine.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Filters

> Filter operators and syntax for search and recommendations

## Overview

Filters narrow search and recommendation results based on product attributes. Use filters for price ranges, categories, availability, and custom metadata.

## Basic Syntax

```typescript theme={null}
const results = await refine.search.text({
  query: 'summer dress',
  topK: 24,
  filters: [
    { field: 'price', operator: 'lte', value: 200 }
  ]
});
```

Each filter has three properties:

<ResponseField name="field" type="string" required>
  The product field to filter on. Use dot notation for nested metadata fields: `metadata.color`.
</ResponseField>

<ResponseField name="operator" type="string" required>
  The comparison operator. See [Operators](#operators) below.
</ResponseField>

<ResponseField name="value" type="any" required>
  The value to compare against. Type depends on the operator.
</ResponseField>

## Operators

### Equality

<Tabs>
  <Tab title="eq (equals)">
    ```typescript theme={null}
    { field: 'metadata.brand', operator: 'eq', value: 'Nike' }
    ```

    Exact match. Case-sensitive for strings.
  </Tab>

  <Tab title="ne (not equals)">
    ```typescript theme={null}
    { field: 'metadata.brand', operator: 'ne', value: 'Generic' }
    ```

    Excludes exact matches.
  </Tab>
</Tabs>

### Comparison

<Tabs>
  <Tab title="gt (greater than)">
    ```typescript theme={null}
    { field: 'price', operator: 'gt', value: 50 }
    ```

    Greater than (exclusive).
  </Tab>

  <Tab title="gte (greater than or equal)">
    ```typescript theme={null}
    { field: 'price', operator: 'gte', value: 50 }
    ```

    Greater than or equal (inclusive).
  </Tab>

  <Tab title="lt (less than)">
    ```typescript theme={null}
    { field: 'price', operator: 'lt', value: 100 }
    ```

    Less than (exclusive).
  </Tab>

  <Tab title="lte (less than or equal)">
    ```typescript theme={null}
    { field: 'price', operator: 'lte', value: 100 }
    ```

    Less than or equal (inclusive).
  </Tab>
</Tabs>

### Array Operators

<Tabs>
  <Tab title="in (in array)">
    ```typescript theme={null}
    { field: 'metadata.color', operator: 'in', value: ['red', 'blue', 'green'] }
    ```

    Field value is one of the provided values.
  </Tab>

  <Tab title="nin (not in array)">
    ```typescript theme={null}
    { field: 'metadata.category', operator: 'nin', value: ['clearance', 'discontinued'] }
    ```

    Field value is NOT one of the provided values.
  </Tab>
</Tabs>

### Existence

```typescript theme={null}
{ field: 'metadata.salePrice', operator: 'exists', value: true }
```

Check if a field exists (`true`) or doesn't exist (`false`).

### Text Matching

```typescript theme={null}
{ field: 'title', operator: 'match', value: 'organic' }
```

Partial text match within the field. Case-insensitive.

## Operator Reference

| Operator | Description           | Value Type | Example                                                        |
| -------- | --------------------- | ---------- | -------------------------------------------------------------- |
| `eq`     | Equals                | any        | `{ field: 'brand', operator: 'eq', value: 'Nike' }`            |
| `ne`     | Not equals            | any        | `{ field: 'status', operator: 'ne', value: 'discontinued' }`   |
| `gt`     | Greater than          | number     | `{ field: 'price', operator: 'gt', value: 50 }`                |
| `gte`    | Greater than or equal | number     | `{ field: 'stock', operator: 'gte', value: 1 }`                |
| `lt`     | Less than             | number     | `{ field: 'price', operator: 'lt', value: 100 }`               |
| `lte`    | Less than or equal    | number     | `{ field: 'rating', operator: 'lte', value: 5 }`               |
| `in`     | In array              | array      | `{ field: 'size', operator: 'in', value: ['S', 'M', 'L'] }`    |
| `nin`    | Not in array          | array      | `{ field: 'tag', operator: 'nin', value: ['test'] }`           |
| `exists` | Field exists          | boolean    | `{ field: 'salePrice', operator: 'exists', value: true }`      |
| `match`  | Text contains         | string     | `{ field: 'description', operator: 'match', value: 'cotton' }` |

## Common Patterns

### Price Range

```typescript theme={null}
filters: [
  { field: 'price', operator: 'gte', value: 50 },
  { field: 'price', operator: 'lte', value: 200 }
]
```

### In Stock Only

```typescript theme={null}
filters: [
  { field: 'stock', operator: 'gt', value: 0 }
]
```

### Multiple Categories

```typescript theme={null}
filters: [
  { field: 'metadata.category', operator: 'in', value: ['dresses', 'skirts', 'tops'] }
]
```

### Exclude Sale Items

```typescript theme={null}
filters: [
  { field: 'metadata.onSale', operator: 'ne', value: true }
]
```

### Has Reviews

```typescript theme={null}
filters: [
  { field: 'metadata.reviewCount', operator: 'gte', value: 1 }
]
```

### Brand Exclusion

```typescript theme={null}
filters: [
  { field: 'metadata.brand', operator: 'nin', value: ['Generic', 'Unknown'] }
]
```

## Filter Logic

Multiple filters are combined with **AND** logic. All conditions must be true for a product to be included.

```typescript theme={null}
// Products where:
// - price is between $50-$200 AND
// - color is red, blue, or green AND
// - in stock
filters: [
  { field: 'price', operator: 'gte', value: 50 },
  { field: 'price', operator: 'lte', value: 200 },
  { field: 'metadata.color', operator: 'in', value: ['red', 'blue', 'green'] },
  { field: 'stock', operator: 'gt', value: 0 }
]
```

<Note>
  OR logic isn't directly supported. Use the `in` operator for "field equals A OR field equals B" scenarios.
</Note>

## Metadata Fields

Access nested metadata using dot notation:

```typescript theme={null}
// Product structure
{
  productId: 'sku_001',
  title: 'Summer Dress',
  price: 79.99,
  metadata: {
    brand: 'Fashion Co',
    color: 'red',
    sizes: ['S', 'M', 'L'],
    details: {
      material: 'cotton',
      origin: 'Italy'
    }
  }
}

// Filter examples
{ field: 'metadata.brand', operator: 'eq', value: 'Fashion Co' }
{ field: 'metadata.color', operator: 'in', value: ['red', 'blue'] }
{ field: 'metadata.details.material', operator: 'eq', value: 'cotton' }
```

## Sorting

Combine filters with sorting:

```typescript theme={null}
const results = await refine.search.text({
  query: 'shoes',
  topK: 24,
  filters: [
    { field: 'price', operator: 'gte', value: 50 },
    { field: 'stock', operator: 'gt', value: 0 }
  ],
  sortBy: {
    field: 'price',
    order: 'ascending'  // 'ascending' | 'descending'
  }
});
```

Available sort fields depend on your catalog schema. Common options:

* `price`
* `metadata.rating`
* `metadata.popularity`
* `metadata.createdAt`

<Warning>
  Sorting by `relevance` (default) uses the AI ranking. Sorting by other fields overrides the AI ranking.
</Warning>

## Filter Options in Response

Search responses include available filter values:

```typescript theme={null}
const results = await refine.search.text({ query: 'dress', topK: 24 });

console.log(results.filterOptions);
// [
//   { field: 'metadata.color', values: ['red', 'blue', 'black', ...] },
//   { field: 'metadata.size', values: ['XS', 'S', 'M', 'L', 'XL'] },
//   { field: 'metadata.brand', values: ['Brand A', 'Brand B', ...] }
// ]
```

Use this to build dynamic filter UIs:

```typescript theme={null}
function buildFilterUI(filterOptions: FilterOption[]) {
  return filterOptions.map(option => `
    <div class="filter-group">
      <h4>${formatFieldName(option.field)}</h4>
      ${option.values.map(value => `
        <label>
          <input type="checkbox" 
                 data-field="${option.field}" 
                 data-value="${value}" />
          ${value}
        </label>
      `).join('')}
    </div>
  `).join('');
}
```

## Performance Tips

<Tip>
  * Filter on indexed fields for best performance
  * Use `in` with small arrays (under 100 values)
  * Avoid `match` on large text fields when possible
  * Combine price ranges into a single range filter
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Text Search" icon="magnifying-glass" href="/sdk/search/text-search">
    Search with text queries
  </Card>

  <Card title="Recommendations" icon="wand-magic-sparkles" href="/sdk/recommendations/overview">
    Filter recommendations too
  </Card>
</CardGroup>
