Overview
The belongsTo relationship represents a many-to-one (N:1) association where the current model belongs to another model. For example, a Post belongs to a User.
This is the inverse of hasOne and hasMany relationships.
Method Signature
belongsTo(RelatedClass, foreignKey = null, ownerKey = 'id')
The related Model class that this model belongs to
foreignKey
string
default:"{RelatedClass._table}_id"
The foreign key column in the current model that references the related model.If not specified, defaults to the related model’s table name + _id (e.g., user_id for a User model).
The primary key column in the related model that the foreign key references.Typically the id column of the parent model.
Basic Usage
Define the Relationship
class Post extends Model {
static _table = "Posts";
author() {
return this.belongsTo(User, "user_id", "id");
}
}
Query with Eager Loading
Use with() to load the relationship and avoid N+1 queries:
// Load posts with their authors
const posts = Post.with("author").get();
posts.each(post => {
Logger.log(post.title);
Logger.log(post.author.name); // Author is already loaded
});
Without Eager Loading (Not Recommended)
// ❌ Creates N+1 queries
const post = Post.first();
const author = User.find(post.user_id); // Additional query
Examples
Post Belongs to User
class User extends Model {
static _table = "Users";
}
class Post extends Model {
static _table = "Posts";
author() {
return this.belongsTo(User, "user_id", "id");
}
}
// Usage
const posts = Post.with("author").where("published", true).get();
posts.each(post => {
Logger.log(`${post.title} by ${post.author.name}`);
});
Comment Belongs to Post and User
class Comment extends Model {
static _table = "Comments";
post() {
return this.belongsTo(Post, "post_id");
}
author() {
return this.belongsTo(User, "user_id");
}
}
// Load multiple relationships
const comments = Comment.with("post", "author").get();
comments.each(comment => {
Logger.log(`${comment.author.name} commented on "${comment.post.title}"`);
Logger.log(`Comment: ${comment.text}`);
});
Custom Foreign Key
class Order extends Model {
static _table = "Orders";
customer() {
// Custom foreign key: customer_id instead of user_id
return this.belongsTo(User, "customer_id", "id");
}
}
Return Value
When eager loaded with with(), the relationship property will contain:
- The related Model instance if a match is found
null if no related record exists
const post = Post.with("author").first();
if (post.author) {
Logger.log(post.author.name); // Model instance
} else {
Logger.log("No author found");
}
Database Schema
For a belongsTo relationship, the foreign key is stored in the current model’s table:
Users table:
┌────┬──────────┬─────────────────┐
│ id │ name │ email │
├────┼──────────┼─────────────────┤
│ 1 │ John Doe │ [email protected]│
└────┴──────────┴─────────────────┘
Posts table:
┌────┬─────────┬───────────────┬─────────┐
│ id │ user_id │ title │ body │
├────┼─────────┼───────────────┼─────────┤
│ 1 │ 1 │ First Post │ ... │
│ 2 │ 1 │ Second Post │ ... │
└────┴─────────┴───────────────┴─────────┘
The user_id in Posts references the id in Users.
Nested Relationships
Load relationships of relationships using dot notation:
// Load comments with their post and the post's author
const comments = Comment.with("post.author").get();
comments.each(comment => {
Logger.log(`Comment on "${comment.post.title}"`);
Logger.log(`Post author: ${comment.post.author.name}`);
});
Always use eager loading with with() to avoid the N+1 query problem. This loads all related records in a single additional query.
Good: Eager Loading (2 queries)
// ✅ Efficient: 2 queries total (Posts + Users)
const posts = Post.with("author").get();
posts.each(post => {
Logger.log(post.author.name); // No additional query
});
Bad: N+1 Problem (N+1 queries)
// ❌ Inefficient: 1 + N queries (1 for posts, N for each author)
const posts = Post.all();
posts.each(post => {
const author = User.find(post.user_id); // Additional query per post!
Logger.log(author.name);
});
- HasMany - Define one-to-many relationships (inverse of belongsTo)
- HasOne - Define one-to-one relationships
- ManyToMany - Define many-to-many relationships with pivot tables