-
Notifications
You must be signed in to change notification settings - Fork 1
Relations
The relations plugin is heavily inspired by Laravel Eloquent. Kex borrows the naming conventions, database schema, and event argument names from Eloquent. If some concepts in this wiki page are not clear enough it's possible that the Eloquent docs will clear them up to you.
- Declaring relations
- Querying relations
- Nested relations
- Modifying the include query
- Supported relations
const {
HasMany,
HasOne,
BelongsTo,
BelongsToMany
} = require('@baethon/kex')
const User = kex.createModel('User', {
relations: {
messages: new HasMany('Message'),
settings: new HasOne('Setting'),
team: new BelongsTo('Team'),
tags: new BelongsToMany('Tag')
}
})
The relations plugin allows fetching the related records with the main query.
const usersList = await User.query()
.include('team')
/**
[
{
id: 1,
team: {
id: 2,
name: 'The Team'
}
}
]
*/
When using include()
, kex will generate N+1
queries (where N
is the number of included relations).
Each relation will have in Model a query builder factory method. It creates a query builder, which allows fetching the related data.
const team = await User.team(userId)
const tags = await User.tags(userId)
You can include()
the relations of relation.
const usersList = await User.query()
.include('team.organization')
/**
[
{
id: 1,
team: {
id: 2,
name: 'The Team',
organization: { id: 1, name: 'ACME' }
}
}
]
*/
In general, the include()
method will fetch all of the related records. When the related model has some global scopes, they will be applied.
It's possible to alter the query for the related model during the query:
const usersList = await User.query()
.include({
messages: qb => {
// qb is instanceof Message model
qb.recent() // <-- use the recent() scope method
}
})
One-to-one relation where the base model is the "parent" for the related model.
const { HasOne } = require('@baethon/kex')
const User = kex.createModel('User', {
relations: {
settings: new HasOne('Setting', /** options */)
}
})
Example table schema:
+-----------------+ +----------------------+
| users | | settings |
+-----------------+ +----------------------+
| id (localKey) | <--- | id |
| | \---- | user_id (foreignKey) |
+-----------------+ +----------------------+
The HasOne
relation supports the following options:
-
foreignKey
(optional;String
) -
localKey
(optional;String
; default:id
)
One-to-many relation where the base model is the "parent" for the related models.
const { HasMany } = require('@baethon/kex')
const User = kex.createModel('User', {
relations: {
messages: new HasMany('Message', /** options */)
}
})
Example table schema:
+---------------+ +----------------------+
| users | | messages |
+---------------+ +----------------------+
| id (localKey) | <--- | id |
| | \---- | user_id (foreignKey) |
+---------------+ +----------------------+
The HasMany
relation supports the following options:
-
foreignKey
(optional;String
) -
localKey
(optional;String
; default:id
)
One-to-one relation where the base model is a "child" of the related model.
const { BelongsTo } = require('@baethon/kex')
const User = kex.createModel('User', {
relations: {
settings: new BelongsTo('Organization', /** options */)
}
})
Example table schema:
+---------------+ +------------------------------+
| organization | | users |
+---------------+ +------------------------------+
| id (otherKey) | <--- | id |
| | \---- | organization_id (foreignKey) |
+---------------+ +------------------------------+
The BelongsTo
relation supports the following options:
-
otherKey
(optional;String
; default:id
) -
foreignKey
(optional;String
)
Many-to-many relation which requires a pivot table to associate the models.
const { BelongsToMany } = require('@baethon/kex')
const User = kex.createModel('User', {
relations: {
tags: new BelongsToMany('Tag', /** options **/)
}
})
Example table schema:
+-----------------+ +---------------------------+ +----------------+
| tags | | tag_user (table) | | users |
+-----------------+ +---------------------------+ +----------------+
| id (relatedKey) | <- | user_id (foreignPivotKey) | ---> | id (parentKey) |
| | \- | tag_id (relatedPivotKey) | | |
+-----------------+ +---------------------------+ +----------------+
The BelongsToMany
relation supports the following options:
-
table
(optional;String
) the name of the pivot table; by default it's a snake_case version of models table names (in singular form) joined in alphabetical order -
foreignPivotKey
(optional;String
) -
relatedPivotKey
(optional;String
) -
parentKey
(optional;String
) -
relatedKey
(optional;String
)