> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brussle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Querying answers

> Answers are data: filter, sort and rank on them, read only current answers, and count them per group.

Answers are data. A query filters, sorts and ranks on [answers](/concepts/answers) as on any other field. A query can also read only the answers that are current. It can find the answers that one version of a judgment or an engine made.

For example, this query finds the payments that have a `settles` pick. It ranks them by `escape_p`, the lowest first. It returns only current answers:

```json POST /v1/namespaces/acme%2Fprod/query theme={"theme":{"light":"css-variables","dark":"css-variables"}}
{
  "filters": ["And", [
    ["attributes.kind", "Eq", "payment"],
    ["answers.settles.thresholds.unmatched", "Eq", false]
  ]],
  "rank_by": ["answers.settles.escape_p", "asc"],
  "top_k": 100,
  "include": {"attributes": ["block"], "answers": ["settles"], "state": false},
  "answers": "fresh_only",
  "consistency": "strong"
}
```

* `settles` is the judgment that matches a payment to an open invoice. See [match one record to another](/guides/entity-matching).
* The `unmatched` threshold is true when `escape_p`, the probability of no match, is at least 0.3. Thus, the filter keeps the payments with a pick.
* Each row has its `id`, its `revision`, the `block` attribute and the `settles` answer.

## Filters

A filter is one of these:

* `[field, op, value]`;
* `["And", [...]]` or `["Or", [...]]`;
* `["Not", filter]`.

The operators are `Eq`, `NotEq`, `In`, `NotIn`, `Lt`, `Lte`, `Gt`, `Gte`, `Glob`, `Contains` (on arrays of strings) and `Exists`.

A comparison on a missing field is false. `NotEq` and `NotIn` on a missing field are true. Thus, `["answers.settles.value", "NotEq", "none_of_the_above"]` also matches the payments that have no answer yet. To leave those payments out, add `["answers.settles.value", "Exists", true]`.

## Fields you can filter on

You can filter on `id`, `revision`, `updated_at` and `attributes.*`. You cannot filter on `state`.

For each judgment, you can also filter on these fields of its answer, as `answers.<j>.<field>`:

| Field | What it holds |
| - | - |
| `p` | The probability of yes, for a `bool`. |
| `value` | The most probable option, for a `choice`. |
| `score` | The mean of the level values, for a `score`. |
| `dist.{option}` | The probability of one option. |
| `escape_p` | The probability of `none_of_the_above`, for a `choice`. |
| `thresholds.{name}` | The result of a named [threshold](/concepts/judgments#thresholds), `true` or `false`. |
| `features.{feature}` | The value of a [feature](/concepts/relations#numbers-from-relations-features). |
| `freshness` | Whether the answer is current. See [read only current answers](#read-only-current-answers). |
| `judgment_version` | The version of the judgment that made the answer. |
| `engine_version` | The engine version that made the answer. |

### Find the answers of one version

`judgment_version` and `engine_version` find the answers that one version of the judgment or of the engine made. For example, you activate version 4 of `settles`. This filter finds the answers that versions 1 to 3 made:

```json theme={"theme":{"light":"css-variables","dark":"css-variables"}}
["answers.settles.judgment_version", "Lt", 4]
```

* **`judgment_version`** is an integer. Compare it with `Eq`, `NotEq`, `Lt`, `Lte`, `Gt`, `Gte`, `In` or `NotIn`, or test it with `Exists`.
* **`engine_version`** is a string. For an engine version that is not pinned, such as jev `current` or gpt-6-luna `current`, it holds the label of the [epoch](/guides/change-a-judgment#epochs), a period in which the engine's behaviour stays the same, such as `current+2026-09-24.1`. Compare it with `Eq`, `NotEq`, `In` or `NotIn`, or test it with `Exists`. The label does not name the engine. Each engine numbers its own epochs, so two engines can have the same label. A query cannot filter on the engine's name. A judgment changes its engine only in a new version, so filter on `judgment_version` as well.
* You can also rank on both fields.

An answer from an earlier version of the judgment reads `stale`, with `stale_reason` `older_version`. A new engine version, such as a new epoch of an engine version that is not pinned, never makes an answer stale. Thus, to compare the answers of two epochs, filter on `engine_version`. See [versions](/concepts/judgments#versions).

### Filter on a feature

A feature filter names the judgment and the feature. For example, a judgment `invoice_settlement` keeps `matched_payments.count` as a feature. This filter finds the invoices with two or more matched payments:

```json theme={"theme":{"light":"css-variables","dark":"css-variables"}}
["answers.invoice_settlement.features.matched_payments.count", "Gte", 2]
```

* All text after `features.` is the name of the feature. It must be a feature of that judgment.
* You can compare it with numbers (`Eq`, `NotEq`, `Lt`, `Lte`, `Gt`, `Gte`, `In`, `NotIn`), or test it with `Exists`.
* The filter reads the value stored with the answer. That value follows the related documents after the judgment's debounce.
* A `window` counts back from the document's newest activity, not from today.
* If freshness matters, also check the answer's `freshness`.

## Read only current answers

Each answer has a [freshness](/concepts/freshness). A query can use it in two ways:

* **`answers: "fresh_only"`** removes each row whose included answers are not `fresh`. It checks only the judgments that `include.answers` names. A row with no answer for one of those judgments is also removed.
* **A filter on `freshness`** reads one judgment's freshness. For example, `["answers.settles.freshness", "Eq", "fresh"]`.

`fresh_only` and a filter on `fresh` leave out an answer from an earlier version of the judgment, because that answer reads `stale`.

A filter on `pending` tells you if a judgment has caught up with your writes. A query for one `pending` answer returns no row when it has. A judgment's `judged_through` tells you too, and reads no documents. See [is a judgment caught up?](/concepts/freshness#is-a-judgment-caught-up).

## Rank and page

* **`rank_by`** is one field and a direction. The default is `["updated_at", "desc"]`. Brussle breaks ties by `id`.
* **`top_k`** is at most 1,000. `more: true` means that more rows matched.
* **`cursor`** gets the next page. Send the `next_cursor` of the previous page. A cursor lasts 10 minutes. It keeps the namespace as it was at the first page. Thus, all pages agree with each other.
* **`consistency: "eventual"`** can serve a view of the namespace up to 60 seconds old, for lower latency. The default is `strong`, which sees each write that Brussle acknowledged before the query.
* **Large scans are refused.** If the estimated scan of a query is more than 4 GB, Brussle refuses it with `too_large` and the estimate. Brussle does not bill it. Add attribute filters to make the scan smaller.

Some filters read every document in the namespace, such as a filter on `pending`. See [tradeoffs](/tradeoffs) for which filters are fast.

## Which judgments you can filter on

You can filter or rank on any judgment except an `on_read` judgment.

* An `on_read` answer exists only after something reads it. A filter on an `on_read` judgment returns `invalid_request`. To filter on it, switch it to `on_change` first. Brussle then backfills the missing answers after you confirm an estimate. Brussle never backfills without your confirmation.
* `on_change` keeps each answer current. Use this policy for the judgments that you filter on.
* Filters read `periodic` and `manual` answers as they are stored.

## Read one document

`GET /namespaces/{ns}/documents/{id}` returns one document with all its answers, and their history on request. See [reading documents](/concepts/documents#reading).

## Count answers per group

A query returns documents. To count answers for each value of a key, such as the matched payments for each customer each month, declare a [group](/guides/groups). A group keeps counts, sums and averages over documents and answers for each key value. You read its rows when you want them.

## Get told when a document matches

A [subscription](/concepts/subscriptions) is a saved query. It sends an event when a document starts or stops matching its filter. Its filter uses the grammar on this page, except `freshness`.


## Related topics

- [Answers](/concepts/answers.md)
- [Documents](/concepts/documents.md)
- [Subscriptions](/concepts/subscriptions.md)
- [Judgments](/concepts/judgments.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.