---
title: Highlighting
description: Generate snippets for portions of the source text that match the query string
canonical: https://docs.paradedb.com/documentation/full-text/highlight
---
Highlighting is an expensive process and can slow down query times. We
recommend passing a `LIMIT` to any query where `pdb.snippet` or `pdb.snippets`
is called to restrict the number of snippets that need to be generated.
Highlighting is not supported for fuzzy search.
Highlighting refers to the practice of visually emphasizing the portions of a document that match a user's
search query.
## Basic Usage
`pdb.snippet()` can be added to any query where an `@@@` operator is present. `pdb.snippet` returns the single best snippet, sorted by relevance score.
The following query generates highlighted snippets against the `description` field.
```sql SQL
SELECT id, pdb.snippet(description)
FROM mock_items
WHERE description ||| 'shoes'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippet
MockItem.objects.filter(
description=ParadeDB(Match('shoes', operator='OR'))
).annotate(
snippet=Snippet('description')
).values('id', 'snippet')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("shoes")
.with_snippet(:description)
.select(:id)
.limit(5)
```
The leading indicator around the highlighted region.
The trailing indicator around the highlighted region.
Max number of characters for a highlighted snippet. A snippet may contain
multiple matches if they are close to each other.
By default, `` encloses the snippet. This can be configured with `start_tag` and `end_tag`:
```sql SQL
SELECT id, pdb.snippet(description, start_tag => '', end_tag => '')
FROM mock_items
WHERE description ||| 'shoes'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippet
MockItem.objects.filter(
description=ParadeDB(Match('shoes', operator='OR'))
).annotate(
snippet=Snippet('description', start_sel='', stop_sel='')
).values('id', 'snippet')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("shoes")
.with_snippet(:description, start_tag: "", end_tag: "")
.select(:id)
.limit(5)
```
## Multiple Snippets
`pdb.snippets()` returns an array of snippets, allowing you to retrieve multiple highlighted matches from a document. This is particularly useful when a document has several relevant matches spread throughout its content.
```sql SQL
SELECT id, pdb.snippets(description, max_num_chars => 15)
FROM mock_items
WHERE description ||| 'artistic vase'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippets
MockItem.objects.filter(
description=ParadeDB(Match('artistic vase', operator='OR'))
).annotate(
snippets=Snippets('description', max_num_chars=15)
).values('id', 'snippets')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("artistic vase")
.with_snippets(:description, max_chars: 15)
.select(:id)
.limit(5)
```
```ini Expected Response
id | snippets
----+-----------------------------------------
19 | {Artistic,"ceramic vase"}
(1 row)
```
The leading indicator around the highlighted region.
The trailing indicator around the highlighted region.
Max number of characters for a highlighted snippet. When `max_num_chars` is
small, multiple snippets may be generated for a single document.
The maximum number of snippets to return per document.
The number of snippets to skip before returning results. Use with `limit` for
pagination.
The order in which to sort the snippets. Can be `'score'` (default, sorts by
relevance) or `'position'` (sorts by appearance in the document).
### Limiting and Offsetting Snippets
You can control the number and order of snippets returned using the `limit`, `offset`, and `sort_by` parameters.
For example, to get only the first snippet:
```sql SQL
SELECT id, pdb.snippets(description, max_num_chars => 15, "limit" => 1)
FROM mock_items
WHERE description ||| 'running'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippets
MockItem.objects.filter(
description=ParadeDB(Match('running', operator='OR'))
).annotate(
snippets=Snippets('description', max_num_chars=15, limit=1)
).values('id', 'snippets')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("running")
.with_snippets(:description, max_chars: 15, limit: 1)
.select(:id)
.limit(5)
```
To get the second snippet (by skipping the first one):
```sql SQL
SELECT id, pdb.snippets(description, max_num_chars => 15, "limit" => 1, "offset" => 1)
FROM mock_items
WHERE description ||| 'running'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippets
MockItem.objects.filter(
description=ParadeDB(Match('running', operator='OR'))
).annotate(
snippets=Snippets('description', max_num_chars=15, limit=1, offset=1)
).values('id', 'snippets')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("running")
.with_snippets(:description, max_chars: 15, limit: 1, offset: 1)
.select(:id)
.limit(5)
```
### Sorting Snippets
Snippets can be sorted either by their relevance score (`'score'`) or their position within the document (`'position'`).
To sort snippets by their appearance in the document:
```sql SQL
SELECT id, pdb.snippets(description, max_num_chars => 15, sort_by => 'position')
FROM mock_items
WHERE description ||| 'artistic vase'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippets
MockItem.objects.filter(
description=ParadeDB(Match('artistic vase', operator='OR'))
).annotate(
snippets=Snippets('description', max_num_chars=15, sort_by='position')
).values('id', 'snippets')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("artistic vase")
.with_snippets(:description, max_chars: 15, sort_by: :position)
.select(:id)
.limit(5)
```
## Byte Offsets
`pdb.snippet_positions()` returns the byte offsets in the original text where the snippets would appear. It returns a two-dimensional integer array where each nested pair is `[start, end)`: the first value is the byte index of the first highlighted byte, and the second value is the byte index immediately after the last highlighted byte.
```sql SQL
SELECT id, pdb.snippet(description), pdb.snippet_positions(description)
FROM mock_items
WHERE description ||| 'shoes'
LIMIT 5;
```
```python Django
from paradedb import Match, ParadeDB, Snippet, SnippetPositions
MockItem.objects.filter(
description=ParadeDB(Match('shoes', operator='OR'))
).annotate(
snippet=Snippet('description'),
snippet_positions=SnippetPositions('description')
).values('id', 'snippet', 'snippet_positions')[:5]
```
```ruby Rails
MockItem.search(:description)
.matching_any("shoes")
.with_snippet(:description)
.with_snippet_positions(:description)
.select(:id)
.limit(5)
```
```ini Expected Response
id | snippet | snippet_positions
----+----------------------------+-------------------
4 | White jogging shoes | {{14,19}}
3 | Sleek running shoes | {{14,19}}
5 | Generic shoes | {{8,13}}
(3 rows)
```