# Relationships

ODD Platform tracks entity-to-entity relationships as first-class catalog objects. They show up two ways: as **ERD diagrams** between table-class entities (foreign-key-style edges) and as **graph relationships** between graph-store entities (Neo4j-style edges). Both are surfaced under [Data Modelling](/features/data-modelling.md) → Relationships in the UI and through the `/api/relationships` API.

## The two relationship classes

The platform's internal model defines a `DATA_RELATIONSHIP(9)` data-entity class that contains two types:

| Internal type             | API filter value | What it represents                                                                                                                                                                                           |
| ------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ENTITY_RELATIONSHIP(25)` | `ERD`            | Foreign-key-style edges between two table-class entities. Cross-schema references are supported. The collector that catalogs the source emits one `ENTITY_RELATIONSHIP` per detected foreign-key constraint. |
| `GRAPH_RELATIONSHIP(26)`  | `GRAPH`          | Free-form graph edges between graph-store entities (e.g., relationships between nodes in a Neo4j database). Distinct from ERD because the cardinality model is graph-native, not relational.                 |

A relationship is a regular catalog entity — it has an ODDRN, an owner, a namespace inherited from its source / target, and shows up in search alongside datasets. The dedicated UI surface and `/api/relationships` API are for **list and detail navigation** of just the relationship-class entities.

## ERD cardinality model (ENTITY\_RELATIONSHIP)

ERD relationships carry the source-and-target table pair plus a cardinality classifier. Four classifiers are defined upstream:

* `ONE_TO_EXACTLY_ONE` — one source row maps to exactly one target row.
* `ONE_TO_ZERO_OR_ONE` — one source row maps to zero or one target row.
* `ONE_TO_ONE_OR_MORE` — one source row maps to one or more target rows.
* `ONE_TO_ZERO_ONE_OR_MORE` — one source row maps to zero, one, or many target rows.

These mirror the cardinality vocabulary defined in the `odd-collectors` monorepo's [Relationships section](https://github.com/opendatadiscovery/odd-collectors#relationships).

## UI walkthrough

Open **Data Modelling → Relationships** from the top-level navigation (`/data-modelling/relationships`). The list page shows every relationship the user can see across all data sources, with:

* **A table** with columns Name, Type (ERD or GRAPH), Namespace + Datasource, Source entity, Target entity.
* **A type tab strip** filtering by `ALL` / `ERD` / `GRAPH` (matches the API enum).
* **A search input** filtering by name across the visible set.
* **Infinite-scroll pagination** — page size is 30 by default.

Click a row to open the relationship's detail page; the platform routes to the `/api/relationships/erd/{id}` or `/api/relationships/graph/{id}` payload depending on the relationship type.

![Relationships list page — eight ENTITY\_RELATIONSHIP rows from a Snowflake sample-data source, each with its name, type (ENTITY RELATIONSHIP), namespace + datasource, source entity, and target entity. The All / ERD / Graph type-filter strip sits above the table; the right-rail switches between Query Examples and Relationships, the two Data Modelling sub-surfaces.](/files/VySae3Sx4hMRi2x3A5qY)

The same data is also surfaced **per-entity** — every dataset's detail page has a **Relationships** tab (in the same tab strip as Overview / Structure / Lineage / Test reports / Alerts / Query examples / Activity / Discussions) that lists only the relationships in which the current entity participates as Parent or Child:

![Per-entity Relationships tab on the ORDERS table (DS / TABLE) — two relationships: (1) ORDERS\_references\_CUSTOMER with CUSTOMER as Parent and ORDERS as Child, cardinality ONE TO ZERO ONE OR MORE, Is Identifying False; (2) LINEITEM\_references\_ORDERS with ORDERS as Parent and LINEITEM as Child, cardinality ONE TO ZERO ONE OR MORE, Is Identifying True. Each row carries an inline ERD-style cardinality glyph (crow's-foot notation) between the Parent and Child columns.](/files/4TIesWKioG3ElTGhXcAE)

The per-entity view is the operator-relevant perspective: when reading a table's documentation, you see only its incoming and outgoing relationships, not the whole catalog's. The Parent / Child columns and the cardinality glyph match the underlying `ENTITY_RELATIONSHIP` model and the same `/api/relationships/erd/{id}` payload surfaces both in this tab and on the global Data Modelling → Relationships list above.

## API surface

The three endpoints exposed by `RelationshipController` are documented at [API Reference → Relationships](/developer-guides/api-reference/relationships.md) — `GET /api/relationships` (paginated list with optional `type=ERD|GRAPH|ALL` filter and free-text query) plus the two per-type detail endpoints. The same payloads also surface on the source and target dataset's detail pages under the dataset's relationships cluster.

## How relationships get into the catalog

Relationships are populated **by the ingesting collector** during the source-side metadata pull. The platform does not infer relationships from naming conventions or column-name similarity — only what the collector emits is surfaced.

Adapter coverage as of the time of writing (per the upstream [`odd-collectors` Relationships matrix](https://github.com/opendatadiscovery/odd-collectors#relationships)):

| Collector       | Adapter      | Relationship type           | How it's derived                                                                |
| --------------- | ------------ | --------------------------- | ------------------------------------------------------------------------------- |
| `odd-collector` | `postgresql` | `ENTITY_RELATIONSHIP` (ERD) | Foreign-key constraints in the database catalog. Cross-schema FKs are detected. |
| `odd-collector` | `snowflake`  | `ENTITY_RELATIONSHIP` (ERD) | Foreign-key constraints in the database catalog. Cross-schema FKs are detected. |

{% hint style="info" %}
**No other adapter currently emits relationships.** The `GRAPH_RELATIONSHIP` type is reserved in the platform model for graph-store sources (e.g., Neo4j edges), but no adapter in the published `odd-collectors` Relationships matrix currently surfaces graph relationships at the time of writing — operators using a Neo4j adapter today get nodes catalogued without their inter-node edges. This is an upstream collector-side gap; if your deployment relies on graph relationships, follow the upstream repo for adapter changes.
{% endhint %}

## Where to next

* [Data Modelling overview](/features/data-modelling.md) — parent section; pairs Relationships with Query Examples.
* [Query Examples](/features/data-modelling/query-examples.md) — the other Data Modelling sub-surface.
* [Integrations → odd-collector](/integrations/integrations/odd-collector.md) — the generic collector that hosts the PostgreSQL and Snowflake adapters surfacing ERD relationships today; the per-adapter feature matrix on that page calls out ERD support explicitly.
* [Main Concepts](/introduction/main-concepts.md) — for the broader catalog vocabulary that names these entities.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opendatadiscovery.org/features/data-modelling/relationships.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
