# How search understands a query

OrbSearch reads what a query names in the shop's own words, such as a category, a color or a width, and searches only the words that are left.

A shopper who types "graues Sofa bis 220 cm" (grey sofa up to 220 cm) means a page, not five words. OrbSearch reads what the query names before it searches, and the answer says what it read.

## What the query named

The answer's [resolution](/docs/reference/glossary#resolution) holds what the query named: a `category`, `filters`, the `text` left over, and whether the query is `complete`:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=graues%20Sofa%20bis%20220%20cm' \
  | jq -c '.resolution, [.sections[] | select(.type == "product") | .hits[].entity]'
```

```json title="Answer: 200 · 23 ms · release b25a6aaa"
{"category":"wohnen/sofas","filters":{"color":"grey","width":{"lte":220}},"text":"","complete":true}
["product:SOFA-ASKA-2","product:SOFA-NIKO-SCHLAF"]
```

"Sofa" named the category `wohnen/sofas` (living/sofas), "graues" the color grey and "bis 220 cm" a width. No word is left as text, so the listing holds the two grey sofas up to 220 cm. Such a query names a whole page, so the answer also carries a `redirect` to it ([URLs and redirects](/docs/urls)).

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

## Where the names come from

Every name comes from the shop itself, and the [trace](/docs/reference/glossary#trace) says which entry each word matched:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=graues%20Sofa%20bis%20220%20cm&debug=1' \
  | jq -c '.trace.steps[] | select(.step == "resolve") | .detections[] | {words, entry, pattern}'
```

```json title="Answer: 200 · 13 ms · release b25a6aaa"
{"words":"Sofa","entry":"the title \"Sofas\" of the category wohnen/sofas","pattern":null}
{"words":"bis 220 cm","entry":"width up to 220 cm","pattern":"width-at-most"}
{"words":"graues","entry":"the label \"Grau\" of the color grey","pattern":null}
```

| Step      | Decision                                                                            |
| --------- | ----------------------------------------------------------------------------------- |
| `resolve` | “Sofa” → category wohnen/sofas · “bis 220 cm” → width ≤ 220 · “graues” → color grey |

OrbSearch's own steps took 1.36 ms and the engine's call 8.71 ms, 10.07 ms in all.

A query is read with four kinds of entry:

- **The catalog's own words:** category titles, brand names and the labels of attribute values, such as "Grau" (grey), also in their inflected forms ("graues").
- **Aliases** a value lists in `attributes.json`, such as "gray" for grey.
- **[Synonyms](/docs/reference/glossary#synonym):** "couch" names the sofas through the group of `couch` and `sofa`, and its detection names that group in `synonym`.
- **[Patterns](/docs/reference/glossary#pattern):** the shop's phrases, such as `bis {width} cm`, `{seats}-sitzer` (seater) or "im Angebot" (on sale), and built-in ones for a price or a size with its unit.

Values are read only for attributes marked `detect_in_query`. A word that names two things stays text, and the step's `kept` says why. Merchants add [synonyms](/docs/synonyms) and [patterns](/docs/patterns).

**Reference:** [`resolve`](/docs/reference/trace#resolve) · [`Detection`](/docs/reference/trace#Detection) · [`detect_in_query`](/docs/reference/release-files/attributes#detect_in_query)

## Take back what the query named

A shopper who meant the word, not the filter, removes its chip. Send the detection back in `dismissed`, and its words stay text however often the query is sent again:

```sh title="Terminal"
curl -s http://127.0.0.1:7800/v1/search -H 'Content-Type: application/json' \
  -d '{ "query": "graues Sofa", "dismissed": [{ "field": "color", "value": "grey" }] }' \
  | jq -c '.resolution'
```

```json title="Answer: 200 · 4.3 ms · release b25a6aaa"
{"category":"wohnen/sofas","text":"graues","complete":false}
```

"graues" is searched as a word again, within the sofas. Without a `value`, every detection of the field is taken back, such as `{ "field": "width" }`.

Only `POST` carries `dismissed`. The search page keeps it in its URL as `ignore`, such as `/suche?q=graues+Sofa&ignore=color:grey`, which `/v1/resolve` reads back as `dismissed` ([URLs and redirects](/docs/urls)).

<Callout type="info">
    A filter a rule sets is the merchant's, so no request takes it back. A filter the shopper chose leaves `filters`
    instead.
</Callout>

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

## How the words match

The words left as text are searched rarest first. Where no product holds every word, the words most products hold give way:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=Lund%20Samt&debug=1' \
  | jq -r '.trace.steps[] | select(.step == "rank") | .sections[] | select(.type == "product")
      | .hits[] | .entity, (.why[] | select(.because.kind == "text") | .sentence)'
```

```text title="Answer: 200 · 12 ms · release b25a6aaa"
product:SOFA-LUND-3
Found by 1 of the query's 2 words, without typos, in title.
```

No product is both the Lund sofa and "Samt" (velvet). Three products hold "Samt" and one holds "Lund", so the search finds the Lund sofa instead of every velvet product. Products that hold every word still rank first. The sections beside the products drop words from the end instead.

Which fields a type's words are looked for in, and how many typos they forgive, is set per type in `types.json`.

**Reference:** [`rank`](/docs/reference/trace#rank) · [`search`](/docs/reference/release-files/types#search) · [`typos`](/docs/reference/release-files/types#typos)

## Other languages

The shop's own words resolve in every locale it writes them in. The same query in English names the same page:

```sh title="Terminal"
curl -s 'http://127.0.0.1:7800/v1/search?query=grey%20sofa%20up%20to%20220%20cm&locale=en' | jq -c '.resolution'
```

```json title="Answer: 200 · 6.2 ms · release b25a6aaa"
{"category":"wohnen/sofas","filters":{"color":"grey","width":{"lte":220}},"text":"","complete":true}
```

The built-in knowledge covers German and English only: inflected forms, color words, and the price and quantity bounds such as "bis" and "under". A shop in another language writes what it needs as synonyms and patterns.

**Reference:** [`patterns.json`](/docs/reference/release-files/patterns) · [`synonyms.json`](/docs/reference/release-files/synonyms)

## Next

- [Search and browse](/docs/search): the request and the answer around the resolution.
- [When nothing is found](/docs/no-results): what happens when what a query named matches nothing.
- [Synonyms](/docs/synonyms) and [Patterns](/docs/patterns): teach the shop its shoppers' words.
