HasManyThrough Relationship
The HasManyThrough relationship represents a multi-hop or chained relationship accessed through intermediate models. It allows you to chain multiple relationships (even of different types) to reach a related set of records through one or more intermediary models.
Tip
HasManyThrough is not the same as ManyToMany. HasManyThrough is for chaining multiple relationships (of any type), while ManyToMany is specifically for a symmetric many-to-many relationship using a join table.
Explanation
For example, a User has many Comments through Posts:
In this example, you can access all users who commented on a user's posts by chaining through posts and comments.
Defining the Relationship
The relationship is defined in your model configuration under the relationships
property as a tuple:
[HasManyThrough, chain: Array<RelationshipTuple>]
Parameters
HasManyThrough
: The relationship type.chain
: An array of relationship tuples defining the path through intermediate models.
Example
{
models: {
users: {
schema: '++id, email, createdAt, updatedAt',
properties: ['id', 'email', 'password'],
primaryKey: 'id',
relationships: {
posts: [HasMany, 'posts', 'user_id'],
comments: [HasMany, 'comments', 'user_id'],
commenters: [HasManyThrough, [
[HasMany, 'posts', 'user_id'], // First hop: User → Posts
[HasMany, 'comments', 'post_id'], // Second hop: Posts → Comments
[BelongsTo, 'users', 'user_id'], // Final hop: Comments → User
]]
}
},
posts: {
schema: '++id, user_id, title, body',
properties: ['id', 'user_id', 'title', 'body'],
relationships: {
comments: [HasMany, 'comments', 'post_id']
}
},
comments: {
schema: '++id, post_id, user_id, body',
properties: ['id', 'post_id', 'user_id', 'body'],
relationships: {
user: [BelongsTo, 'users', 'user_id']
}
}
}
}
Accessing the Relationship
const user = await User.find(1)
const commenters = await user.commenters
user.commenters.forEach(commenter => {
commenter.onChange((updatedCommenter) => {
console.log('Commenter updated:', updatedCommenter)
})
})
user.onPropertyChange('commenters', (newCommenters, oldCommenters) => {
console.log('Commenters collection changed:', { new: newCommenters, old: oldCommenters })
})
Note
HasManyThrough is for chaining multiple relationships (even of different types) to reach a related set of records through one or more intermediary models. This is different from ManyToMany, which is specifically for a symmetric many-to-many relationship using a join table. If you want to relate two models directly through a join table, use ManyToMany. If you want to traverse a chain of relationships, use HasManyThrough.