# Sorting

Draw a page's sort control from the answer, send the shopper's choice, and read why a page starts in the order it does.

A page starts in its default order, and the answer lists every order it offers. Draw the sort control from the answer's `sorts`:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?on=category_page&category=wohnen/sofas' | jq -c '.sorts[]'
```

```json title="Answer: 200 · 3.8 ms · release b25a6aaa"
{"code":"relevance","label":"Beste Treffer","default":true}
{"code":"price_asc","label":"Preis aufsteigend"}
{"code":"price_desc","label":"Preis absteigend"}
{"code":"newest","label":"Neueste zuerst"}
{"code":"delivery_time","label":"Schnellste Lieferung"}
```

Each order has the `code` a request sends and a `label` in the request's locale. `default` marks the one the page starts in, here "Beste Treffer" (best match), which is relevance.

**Reference:** [`sorts`](/docs/reference/query-api#search.answer.sorts)

## Sort a page

Send the shopper's choice as `sort`, and leave it out while they keep the default:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?on=category_page&category=wohnen/sofas&sort=price_asc' \
  | jq -r '.sections[] | select(.type == "product") | .hits[] | "\(.entity) \(.fields.sale_price // .fields.price)"'
```

```text title="Answer: 200 · 3.7 ms · release b25a6aaa"
product:SOFA-ASKA-2 649.0
product:SOFA-NIKO-SCHLAF 799.0
product:SOFA-LUND-3 1299.0
product:SOFA-VIDAR-ECK 1899.0
```

A price sorts by what the shopper pays, so `SOFA-ASKA-2` comes first at its sale price. A page's URL leaves `sort` out at the default, so the default page has one address. An unknown code is refused with a `400` that lists the codes there are ([Errors](/docs/search#errors)).

**Reference:** [`sort`](/docs/reference/query-api#search.sort)

## Where a page starts

A search with words starts by relevance. A page without words starts in its category's default sort. The trace's `sort` step says which, in a sentence:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=sofa&debug=1' \
  | jq -r '.trace.steps[] | select(.step == "sort") | .reason'
curl -s 'http://127.0.0.1:7800/v1/search?on=category_page&category=wohnen/sofas&debug=1' \
  | jq -r '.trace.steps[] | select(.step == "sort") | .reason'
```

```text title="Answer: 200 · 3.6 ms · release b25a6aaa"
The request has words, which rank by relevance.
The default layout of categories.json sets relevance as the default sort.
```

The home store's layout starts every page by relevance. A [node](/docs/reference/glossary#node) in `categories.json` can set its own default, and the pages below it inherit it:

```json title="categories.json"
{
    "nodes": [{ "category": "wohnen/sofas", "sort": { "default": "price_asc" } }]
}
```

The nearest node up the tree that sets a default decides, then the layout's `default`, else relevance. The shopper's choice wins over all of them.

**Reference:** [`default.sort`](/docs/reference/release-files/categories#default.sort) · [`nodes.sort`](/docs/reference/release-files/categories#nodes.sort) · [`sort` step](/docs/reference/trace#sort)

## Define the orders

`relevance` is built in. Every other order is defined in `ranking.json`, by a field and a direction:

```json title="tests/fixtures/home/ranking.json (trimmed)"
{
    "sorts": [
        {
            "code": "price_asc",
            "label": { "de": "Preis aufsteigend", "en": "Price: low to high" },
            "by": "price",
            "direction": "asc"
        }
    ]
}
```

A page offers the `options` its node or the layout lists. Where the release lists none, the answer has no `sorts`, and the page offers no choice. A product without a value for the field comes after those that have one.

**Reference:** [`ranking.json` sorts](/docs/reference/release-files/ranking#sorts) · [`sort.options`](/docs/reference/release-files/categories#default.sort.options)

## Next

- [Facets and filters](/docs/facets): narrow the page the shopper sorts.
- [Category pages](/docs/category-pages): browse a category without words.
- [React components](/docs/react): a sort control drawn from `sorts`.
