# Knowledge graph patterns

Model entities and relationships as first-class data for traversal, search, and AI workflows using SurrealDB's graph features.

A knowledge graph models your domain as entities (people,
products, documents, concepts) connected by typed relationships:

-   `document -> cites -> regulation`
-   `person -> works_at -> organisation`
-   `symptom -> associated_with -> condition`

This structure gives you a map of meaning that you can do the following with:

* traverse via single- or multi-hop queries
* enrich with metadata that applies to the relation between one record and another
* combine with search and AI workflows

In SurrealDB, knowledge graphs are built using: - records as nodes
(`person`, `document`, `concept`) - graph relations as edges,
created with
[`RELATE`](/docs/reference/query-language/statements/relate.md)

Unlike simple links, edges are first-class records, so you can
attach rich metadata to relationships.

## Core pattern: entities + typed relationships

A typical pattern looks like this:

```surql
DEFINE TABLE person SCHEMAFULL;
DEFINE TABLE organisation SCHEMAFULL;

DEFINE TABLE works_at SCHEMAFULL
  TYPE RELATION
  FROM person
  TO organisation;

-- Require relationship-specific data on each edge
DEFINE FIELD role        ON works_at TYPE string;
DEFINE FIELD started_at  ON works_at TYPE datetime;
```

Relationships can then be created using a `RELATE` statement:

```surql
RELATE person:alice->works_at->organisation:acme
  SET role = "Engineer",
      started_at = time::now();
```

This lets you query both the connection and the context of the
connection.

## Design tips

### Use stable, explicit identities

Use clear table types (`person`, `document`, `clause`) and stable record
IDs so relationships remain meaningful over time.

### Map out queries ahead of time and give thought to edge names

Mapping out queries ahead of time can help make a decision between how coarse- or fine-grained records and edges should be.

For example, you might want to use a single `wrote` edge to connect a `person` or similar record to their writing:

```surql
SELECT *,
  ->wrote->blog AS blogs,
  ->wrote->comment AS comments
FROM person;

SELECT *,
  ->wrote->(blog, comment) AS all_written
FROM person;
```

The more generic the type, the greater the chance that you may need to use a filter.

```surql
SELECT *,
  ->(wrote WHERE type = "blog")->item AS blogs,
  ->(wrote WHERE type = "comment")->item AS comments
FROM person;
```

A more fine-grained approach with separate blogged and commented edges can be more effective for knowledge-graph and AI use cases, because the relationship semantics are explicit in the graph itself rather than inferred from filters or record types.

```surql
SELECT *,
  ->blogged->blog AS blogs,
  ->commented->comment AS comments
FROM person;
```

As multiple edges can always be combined into a single query, you can make your logic as fine-grained as you can conceptually manage without needing to worry about this having an effect on the queries you put together. The only extra addition to such queries is that of the names of the edge tables involved.

```surql
SELECT *,
  ->(blogged, commented)->(blog, comment) AS all_written
FROM person;
```

## Industry-oriented examples

You can see these patterns applied in real-world schemas in our [sample industry
schemas](/docs/learn/schema-management/schema-design/sample-industry-schemas.md) page.
