Relations and Graph Traversal
SurrealDB is a graph database, so UnrealORM distinguishes between a record link and a graph edge.
Record links
Section titled “Record links”A Field.record stores a RecordId pointer. It does not enforce referential integrity by default.
class Post extends Table.normal({ name: 'post', fields: { author: Field.record(() => User), },}) {}Create a post with a link:
const post = await Post.create(db, { title: 'Hello', author: user.id,});Expand the link at query time:
const posts = await Post.select(db, { select: { title: true, author: { name: true } }, fetch: ['author'],});References with referential integrity
Section titled “References with referential integrity”Enable the experimental record_references capability and use reference:
author: Field.record(() => User, { reference: { onDelete: 'cascade' },})Graph edges
Section titled “Graph edges”A relation table must declare in and out fields:
class Follow extends Table.relation({ name: 'follow', schemafull: true, fields: { in: Field.record(() => User), out: Field.record(() => User), since: Field.datetime({ default: surql`time::now()` }), },}) {}Create an edge:
const follow = await Follow.relate(db, { from: alice.id, to: bob.id, orUpdate: true,});Traversing edges in queries
Section titled “Traversing edges in queries”Use surql for graph paths inside typed() or where:
// Followers of a userconst followers = await User.select(db, { select: { name: true, followerNames: typed<string[]>(surql`<-follow.in.name`), }, where: (f) => f.id.eq(alice.id), only: true,});
// Users that alice followsconst following = await User.select(db, { select: { name: true, follows: typed<string[]>(surql`->follow->user.name`), }, where: (f) => f.id.eq(alice.id), only: true,});For complex graph work you can always fall back to raw surql or combine the field proxy with surql templates.