# $fuzzy

The `$fuzzy` operator matches terms that are similar but not identical to the search term.
This is useful for handling typos, misspellings, and minor variations in user input.

### Levenshtein Distance

Fuzzy matching uses Levenshtein distance (also called edit distance) to measure similarity between terms.
The distance is the minimum number of single-character edits needed to transform one word into another.
These edits include:

- **Insertions:** Adding a character ("headphone" → "headphones")
- **Deletions:** Removing a character ("headphones" → "headphone")
- **Substitutions:** Replacing a character ("headphones" → "headphonez")

For example, the Levenshtein distance between "headphons" and "headphones" is 1 (one insertion needed).

### Distance Parameter

The `distance` parameter sets the maximum Levenshtein distance allowed for a match.
The default is 1, and the maximum allowed value is 2.

| Distance | Matches |
|----------|---------|
| 1 | Words with 1 edit (handles most single typos) |
| 2 | Words with up to 2 edits (handles more severe misspellings) |

Higher distances match more terms but may include unintended matches, so use distance 2 only when needed.

### Transposition Cost

A transposition swaps two adjacent characters (e.g., "teh" → "the").
By default, a transposition counts as 1 edit.
Setting `transpositionCostOne: false` counts transpositions as two edits (one deletion + one insertion) instead.

For example, searching for "haedphone" to find "headphone":
- With `transpositionCostOne: true`: Distance is 1 (swap counts as 1)
- Without `transpositionCostOne`: Distance is 2 (swap "ae" → "ea" costs 2)

This is useful when users commonly transpose characters while typing quickly.

### Prefix Matching

Setting `prefix: true` enables fuzzy prefix matching, which matches terms that start with a fuzzy
variation of the search term. This combines the typo tolerance of fuzzy matching with prefix
matching for incomplete words.

For example, searching for "headpho" with `prefix: true`:
- Matches "headphones" (prefix match)
- Matches "headphone" (prefix match)
- Matches "haedphones" with `transpositionCostOne: true` (fuzzy prefix, handles typo + incomplete word)

This is particularly useful for search-as-you-type autocomplete where users may have typos
in partially typed words.

### Multiple Words

When you provide multiple words to `$fuzzy`, each word is matched with fuzzy tolerance and combined using
a boolean [`$must`](../boolean-operators/must) query.
This means all terms must match (with their respective fuzzy tolerance) for a document to be returned.

For example, searching for "wireles headphons" will match documents containing both "wireless" and "headphones", even with the typos.

### Compatibility

| Field Type | Supported |
|------------|-----------|
| TEXT | Yes |
| U64/I64/F64 | No |
| DATE | No |
| BOOL | No |
| KEYWORD | No |
| FACET | No |

### Examples

<Tabs>

<Tab title="TypeScript">
```ts
// Simple fuzzy (distance 1, handles single typos)
// Matches "headphone" even with the typo "headphon"
await products.query({
  filter: {
    name: { $fuzzy: "headphon" },
  },
});

// Custom distance for more tolerance
// "haedphone" is 2 edits away from "headphone" without taking transposition into account
await products.query({
  filter: {
    name: {
      $fuzzy: {
        value: "haedphone",
        distance: 2,
        transpositionCostOne: false,
      },
    },
  },
});

// Handle character transpositions efficiently
// "haedphone" has swapped "ae", with transpositionCostOne this is 1 edit
await products.query({
  filter: {
    name: {
      $fuzzy: {
        value: "haedphone",
        distance: 1,
        transpositionCostOne: true,
      },
    },
  },
});

// Combine prefix with transposition for robust autocomplete
// Handles both typos and incomplete input like "haedpho" → "headphones"
await products.query({
  filter: {
    name: {
      $fuzzy: {
        value: "haedpho",
        prefix: true,
      },
    },
  },
});

// Multiple words - matches documents containing both terms (with fuzzy tolerance)
// Matches "wireless headphones" even with typos in both words
await products.query({
  filter: {
    name: { $fuzzy: "wireles headphons" },
  },
});
```
</Tab>

<Tab title="Python">
```python
# Simple fuzzy (distance 1, handles single typos)
products.query(filter={"name": {"$fuzzy": "headphon"}})

# Custom distance for more tolerance
products.query(filter={"name": {"$fuzzy": {"value": "haedphone", "distance": 2, "transpositionCostOne": False}}})

# Handle character transpositions efficiently
products.query(filter={"name": {"$fuzzy": {"value": "haedphone", "distance": 1, "transpositionCostOne": True}}})

# Combine prefix with transposition for robust autocomplete
products.query(filter={"name": {"$fuzzy": {"value": "haedpho", "prefix": True}}})

# Multiple words - matches documents containing both terms (with fuzzy tolerance)
products.query(filter={"name": {"$fuzzy": "wireles headphons"}})
```
</Tab>

<Tab title="Redis CLI">
```bash
# Simple fuzzy (distance 1, handles single typos)
SEARCH.QUERY products '{"name": {"$fuzzy": "headphon"}}'

# Custom distance for more tolerance
SEARCH.QUERY products '{"name": {"$fuzzy": {"value": "haedphone", "distance": 2, "transpositionCostOne": false}}}'

# Handle character transpositions efficiently
SEARCH.QUERY products '{"name": {"$fuzzy": {"value": "haedphone", "distance": 1, "transpositionCostOne": true}}}'

# Combine prefix with transposition for robust autocomplete
SEARCH.QUERY products '{"name": {"$fuzzy": {"value": "haedpho", "prefix": true, "transpositionCostOne": true}}}'

# Multiple words - matches documents containing both terms (with fuzzy tolerance)
SEARCH.QUERY products '{"name": {"$fuzzy": "wireles headphons"}}'
```
</Tab>

</Tabs>
