---
title: Sorting
---
## Order by Relevance
The `score` column returned by [`paradedb.score`](/documentation/full-text/scoring) can be used to sort results by
BM25 relevance.
```sql
SELECT description, rating, category, paradedb.score(id)
FROM mock_items
WHERE description @@@ 'shoes'
ORDER BY score DESC
LIMIT 5;
```
## Order by Field
The result set can be ordered by any field in `ASC` or `DESC` order. By default, Postgres orders by `ASC`.
```sql
SELECT description, rating, category
FROM mock_items
WHERE description @@@ 'shoes'
ORDER BY rating DESC
LIMIT 5;
```
## Tiebreaking
Postgres can `ORDER BY` multiple columns to break ties in BM25 scores. In the following query, rows with the same
`score` will be sorted by `rating` in descending order.
```sql
SELECT description, rating, category, paradedb.score(id)
FROM mock_items
WHERE category @@@ 'electronics'
ORDER BY score DESC, rating DESC
LIMIT 5;
```
## Fast Ordering
An `ORDER BY...LIMIT` over a single [text](/documentation/indexing/create_index#text-fields), [numeric](/documentation/indexing/create_index#numeric-fields),
[datetime](/documentation/indexing/create_index#datetime-fields), or [boolean](/documentation/indexing/create_index#boolean-fields) field is automatically "pushed down"
to the BM25 index if the `ORDER BY` field is indexed as [fast](/documentation/indexing/fast_fields). This makes these queries significantly faster.
You can verify if an `ORDER BY...LIMIT` was pushed down by running `EXPLAIN` on the query. If pushdown occurred, a `Custom Scan` with a
`Sort Field` will appear in the query plan.
```sql
-- Pushdown may not occur over very small tables
-- This forces pushdown
SET enable_indexscan = off;
EXPLAIN SELECT description
FROM mock_items
WHERE description @@@ 'shoes'
ORDER BY rating DESC
LIMIT 5;
```
```csv
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=10.00..34.03 rows=5 width=36)
-> Custom Scan (ParadeDB Scan) on mock_items (cost=10.00..34.03 rows=5 width=36)
Table: mock_items
Index: search_idx
Scores: false
Sort Field: rating
Sort Direction: desc
Top N Limit: 5
Tantivy Query: {"WithIndex":{"oid":2073854,"query":{"ParseWithField":{"field":"description","query_string":"shoes","lenient":null,"conjunction_mode":null}}}}
(9 rows)
```
### Ordering by Text Field
If a fast text field is indexed with the `raw` [normalizer](/documentation/indexing/fast_fields#normalizers), `ORDER BY LIMIT` can be pushed down.
If the `lowercase` [normalizer](/documentation/indexing/fast_fields#normalizers) is used, then `ORDER BY lower() LIMIT` (but not `ORDER BY LIMIT`)
can be pushed down.
```sql
CREATE INDEX search_idx ON mock_items
USING bm25 (id, description, category)
WITH (
key_field='id',
text_fields='{
"category": {"fast": true, "normalizer": "lowercase"}
}'
);
-- category uses normalizer = lowercase, so lower(category) can be pushed down
EXPLAIN SELECT description, rating, category
FROM mock_items
WHERE description @@@ 'shoes'
ORDER BY lower(category) DESC
LIMIT 5;
```
```csv
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Limit (cost=10.00..34.05 rows=5 width=584)
-> Custom Scan (ParadeDB Scan) on mock_items (cost=10.00..34.05 rows=5 width=584)
Table: mock_items
Index: search_idx
Scores: false
Sort Field: category
Sort Direction: desc
Top N Limit: 5
Tantivy Query: {"ParseWithField":{"field":"description","query_string":"shoes","lenient":null,"conjunction_mode":null}}
(9 rows)
```
Not all `ORDER BY`s are pushed down. The following queries are not pushed down:
1. `ORDER BY`s over multiple fields for tiebreaking.
2. Using `paradedb.score` with an `ORDER BY` over another field.
3. `ORDER BY` without a `LIMIT`.