Skip to main content

Relations Overview

Hysteria ORM supports rich relation types between models:

  • belongsTo
  • hasOne
  • hasMany
  • manyToMany

Relations are retrieved using batch loading, so one query is made for each relation only if load is called. Be carefull, too many relation retrieve could slow down you overall query Annotations and nested relations are typed inside the retrieved relations.

Example Models

class User extends Model {
@hasMany(() => Post, 'userId')
declare posts: Post[];

@manyToMany(() => Address, () => UserAddress, {
leftForeignKey: 'userId',
rightForeignKey: 'addressId',
})
declare addresses: Address[];
}

class Post extends Model {
@belongsTo(() => User, 'userId')
declare user: User;
}

class Address extends Model {
@manyToMany(() => User, () => UserAddress, {
leftForeignKey: 'addressId',
rightForeignKey: 'userId',
})
declare users: User[];
}

Querying Relations

  • Remember to always select the foreign key in the relation query builder, otherwise the relation will not be filled.

Eager Loading

const users = await User.query().load('posts').many();

Selecting columns

In this case userId must be selected in the relation query builder, otherwise the relation will not be filled.

const users = await User.query().load('posts', (qb) =>
qb.select('id', 'title', 'userId')
).many();

Nested Relations

const users = await User.query().load('posts', (qb) =>
qb.load('user')
).many();

Filtering on Relations

const users = await User.query().load('posts', (qb) =>
qb.where('title', 'Hello World')
).many();

Limiting and Offset

Limiting and offset are referred to the related models, so in this case 10 posts will be selected for each user skipping the first 10. Adding limit or offset will create a CTE to apply the limit and offset to the related models.

const users = await User.query().load('posts', (qb) =>
qb.where('title', 'Hello World').limit(10).offset(10)
).many();

Advanced relation queries

const users = await User.query().load('posts', (qb) =>
qb.annotate("max", "id", "maxId").load("user")
).many();

Best Practices

  • Use load for batch relation loading.
  • Use callbacks for nested and filtered relations.
  • Always define foreign keys explicitly for clarity.

Next: Advanced SQL Features