Skip to main content

Working with Relations

RelationQueryBuilder is a specialized QueryBuilder that enables efficient handling of relationships in your database. With it, you can manage relations without loading entire entities, or easily fetch related data.

Example: Adding a Category to a Post​

Suppose a Post entity has a many-to-many relationship with a Category entity, named categories. Here’s how you can add a new category to this relationship:

await Post.createQueryBuilder()
.relation(Post, "categories")
.of(post)
.add(category);

This is equivalent to:

const post = await Post.findOne({
where: { id: 1 },
relations: { categories: true },
});

post.categories.push(category);
await postRepository.save(post);

Using RelationQueryBuilder is more efficient, as it minimizes operations and directly updates the database. It also avoids performance issues when managing large relations, such as adding new categories to a post with thousands of existing categories.

Using IDs to Bind Entities​

You can reference entities by their IDs instead of loading them. For instance, to add a category with id = 3 to a post with id = 1:

await Post.createQueryBuilder().relation(Post, "categories").of(1).add(3);

For composite primary keys, pass an ID map:

await Post.createQueryBuilder()
.relation(Post, "categories")
.of({ firstPostId: 1, secondPostId: 3 })
.add({ firstCategoryId: 2, secondCategoryId: 4 });

Removing a category from a post:

await Post.createQueryBuilder()
.relation(Post, "categories")
.of(post) // or post ID
.remove(category); // or category ID

Setting Relations​

For one-to-one or many-to-one relations, use set:

await Post.createQueryBuilder()
.relation(Post, "categories")
.of(post) // or post ID
.set(category); // or category ID

To unset a relation, pass null to the set method:

await Post.createQueryBuilder()
.relation(Post, "categories")
.of(post) // or post ID
.set(null);

Loading Relational Entities​

To fetch related entities, use the relational query builder. For instance, if a Post entity has a many-to-many categories relation and a many-to-one user relation:

const post = await Post.findOneBy(Post, { id: 1 });

post.categories = await Post.createQueryBuilder()
.relation(Post, "categories")
.of(post) // or post ID
.loadMany();

post.author = await Post.createQueryBuilder()
.relation(Post, "user")
.of(post) // or post ID
.loadOne();