> ## 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.

# Finding your relations

> Put the data you want related in one namespace, then see which attributes already point at other documents before you declare a relation.

A [relation](/concepts/relations) is an attribute you already write, such as `attributes.account_id` holding an account's `id`, declared on a judgment so it reads the documents on the other end. Before your first judgment, you can ask which of your attributes already look like that.

## Put related data in one namespace

Relations never cross namespaces. A namespace is a [tenant or an environment](/concepts/namespaces#tenants-and-environments), so if you want a judgment to read your CRM records and your support tickets together, write both into the same namespace: `acme/prod/tenant_123`, not `acme/prod/tenant_123/crm` and `acme/prod/tenant_123/support`. Decide this before your first write, since moving documents later means writing them again.

```mermaid theme={"theme":{"light":"css-variables","dark":"css-variables"}}
flowchart LR
  subgraph one["acme/prod/tenant_123"]
    t["support ticket"] -- "attributes.account_id" --> a["CRM account"]
  end
  subgraph crm["acme/prod/tenant_123/crm"]
    a2["CRM account"]
  end
  subgraph support["acme/prod/tenant_123/support"]
    t2["support ticket"]
  end
  t2 -.-x a2
```

In one namespace, a ticket can point at its account and a judgment can read both. Split across two namespaces, a relation on the same `account_id` reads nothing.

This is guidance for the relations you want, not a rule about every source. Data no judgment will ever read together can live in namespaces of its own.

## Ask for suggestions

Once some documents are written, ask for suggestions. It creates nothing, and it is billed like a query, as the bytes of the documents it reads, within a fixed budget.

<CodeGroup>
  ```python Python theme={"theme":{"light":"css-variables","dark":"css-variables"}}
  found = ns.suggest_relations()
  for relation in found["relations"]:
      print(relation["from"], relation["attribute"], "->", relation["to"],
            f'{relation["resolved"]}/{relation["sampled_values"]}')
  ```

  ```ts TypeScript theme={"theme":{"light":"css-variables","dark":"css-variables"}}
  const found = await ns.suggestRelations();
  for (const relation of found.relations) {
    console.log(relation.from, relation.attribute, "->", relation.to, `${relation.resolved}/${relation.sampled_values}`);
  }
  ```

  ```sh curl theme={"theme":{"light":"css-variables","dark":"css-variables"}}
  curl https://api.brussle.com/v1/namespaces/acme%2Fcrm%2Fprod/relations/suggest \
    -H "Authorization: Bearer $BRUSSLE_API_KEY"
  ```
</CodeGroup>

The response is read from a sample of the namespace's documents, up to 1,000:

```json theme={"theme":{"light":"css-variables","dark":"css-variables"}}
{
  "tenant": null,
  "sampled_documents": 1000,
  "kind": {
    "attribute": "type",
    "values": [
      {"value": "ticket", "documents": 612},
      {"value": "invoice", "documents": 301},
      {"value": "account", "documents": 87}
    ],
    "candidates": [{"attribute": "status", "values": [{"value": "open", "documents": 402}, {"value": "paid", "documents": 288}, {"value": "closed", "documents": 210}, {"value": null, "documents": 100}]}]
  },
  "relations": [
    {
      "attribute": "account_id", "from": "ticket", "to": "account",
      "resolved": 97, "sampled_values": 100, "self_references": 0, "unresolved": 3,
      "unresolved_examples": ["acct_0419", "acct_legacy_7", "n/a"],
      "resolved_by_kind": [{"kind": "account", "resolved": 97}],
      "documents": 100, "array_lengths": null
    }
  ],
  "complete": true,
  "exhausted": null,
  "budget": {"documents_read": {"used": 1000, "limit": 1000}, "attributes_examined": {"used": 14, "limit": 200}, "ids_looked_up": {"used": 336, "limit": 10000}, "bytes_read": {"used": 61240, "limit": 16777216}},
  "note": "A value that resolves to a document id is evidence of a possible relation, not proof of one. Nothing was created: declare a relation on a judgment to use one.",
  "usage": {"bytes_scanned": 61240}
}
```

## Reading the response

**Kinds.** Your documents are split into kinds by one attribute with few distinct values, named in `kind.attribute`, with how many sampled documents hold each value. A status or a plan has as few values as a kind, so the other attributes that could have been the kind are listed in `kind.candidates`. If the wrong one was taken, pass another: `ns.suggest_relations(kind="object")` or `ns.suggestRelations({ kind: "object" })`. When no attribute qualifies, `kind.attribute` is null and the sample is one kind.

**Relations.** Each entry is one attribute on the sampled documents of one kind (`from`, up to 100 documents of it) whose values name live documents:

* `resolved` of `sampled_values`: how many of its present values name another document. The count is of values that are there, not of documents, so an attribute most documents leave out can still resolve 97 of 100.
* `to`: the kind most of those documents are, with every kind in `resolved_by_kind`.
* `unresolved` and up to 5 `unresolved_examples`: values that name no document, such as a deleted record, one not yet written, or a placeholder like `"n/a"`.
* `self_references`: values naming the document that holds them. An account whose `account_id` is its own `id` resolves every time, but it points at itself, not at another record, so those values are counted here and never as `resolved`.
* `array_lengths`: for an attribute holding a list of ids, each element counts as one value, and the lists' shortest, longest and mean lengths are shown beside them.

```mermaid theme={"theme":{"light":"css-variables","dark":"css-variables"}}
flowchart LR
  t["ticket<br/>account_id"] -- "97 of 100 values" --> a["account"]
  t -. "3 name no document" .-x u["acct_0419, acct_legacy_7, n/a"]
```

The entry above, drawn: of the 100 `account_id` values on the sampled tickets, 97 name an account and 3 name no document. Nothing is declared until you put the relation on a judgment.

A value that resolves is **evidence of a possible relation, not proof of one**. A short string such as `"open"` can happen to be some document's `id`. Check what an attribute means before you declare it. All counts are of the sample, not of the namespace: 97 of 100 sampled values means the attribute looks reliable, not that 97% of all values resolve.

## Bounded and repeatable

The work has one budget: documents read, attributes examined, ids looked up and bytes read, each reported in `budget` with its limit. When one runs out before every kind and attribute is examined, you get what was found so far, with `complete: false` and `exhausted` naming the dimension that ran out. Large attribute values, many kinds or long lists of ids are what use it up.

The call is billed like a [query](/pricing): `usage.bytes_scanned` is the bytes of the documents it read, the same as `budget.bytes_read.used`, so the budget also caps what one call costs.

The same namespace state gives the same sample, so asking again without writing gives the same answer. After writes, the sample can change.

## On a template

On a [template](/guides/templates) prefix, such as `acme/prod/*`, the sample is one tenant's documents, named in `tenant`, as an example of what the template's tenants hold. Ask on another tenant's namespace to see its own.

## In the dashboard

A namespace with documents and no judgments opens on its suggestions, so you see your relations before you declare any.

## Next

Declare what you found on a judgment: the documents that point at the one judged, as in [related documents](/guides/related-documents), or the document it points at, as in [the referenced document](/guides/referenced-document).


## Related topics

- [Suggest the relations your documents already hold](/api-reference/judgments/suggest-the-relations-your-documents-already-hold.md)
- [Judge an account with the accounts linked to it](/guides/linked-accounts.md)
- [Keep your data in sync](/guides/keep-data-in-sync.md)
- [Relations](/concepts/relations.md)
- [Summarize every tenant](/guides/tenant-summary.md)


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