undeexcepturi
Version:
TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.
126 lines (86 loc) • 3.33 kB
Markdown
---
title: Relationship Loading Strategies
sidebar_label: Loading Strategies
---
MikroORM supports two loading strategies:
- `select-in` which uses separate queries for each relation - it you populate two relations, you will get three queries - one for the root entity, and one for each populated relation.
- `joined` which uses a single query and joins the relations instead.
> `joined` strategy is supported **only in SQL drivers** and is the **default** for those since v6.
## Configuring the strategy
The loading strategy can be specified both at mapping time and when loading entities, as well as globally in your ORM config.
Given the following entities:
```ts
import { Entity, LoadStrategy, OneToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core';
export class Author {
id!: number;
books = new Collection<Book>(this);
}
export class Book {
id!: number;
author: Author;
}
```
With the default `joined` strategy, this will issue a single query both the `Author` entity and its `books` relation.
```ts
const author = await orm.em.findOne(Author, 1, {
populate: ['books'],
});
```
To override the strategy, you can use the `strategy` option:
```ts
const author = await orm.em.findOne(Author, 1, {
populate: ['books'],
strategy: 'select-in',
});
```
This will issue two SQL statements, one to load the author and another to load all the books belonging to that author:
Alternatively, you can control the strategy in your entity definition.
```ts
import { Entity, LoadStrategy, OneToMany } from '@mikro-orm/core';
export class Author {
// ...
books = new Collection<Book>(this);
}
```
The strategy defined on property level will always take a precedence.
## Changing the loading strategy globally
You can use `loadStrategy` option in the ORM config:
```ts
MikroORM.init({
// ...
populate: ['books'],
loadStrategy: 'select-in', // 'joined' is the default for SQL drivers
});
```
This value will be used as the default, specifying the loading strategy on property level has precedence, as well as specifying it in the `FindOptions`.
## Population `where` condition
The where condition is by default applied only to the root entity. This can be controlled via `populateWhere` option. It accepts one of `all` (default), `infer` (use same condition as the `where` query) or an explicit filter query.
```ts
await em.find(Author, { ... }, {
populate: ['books'],
populateWhere: 'infer', // defaults to `all`
// or specify custom query, will be used via `join on` conditions
// populateWhere: { age: { $gte: 18 } },
});
```
> `populateWhere` can be also set globally, the default is `all`.
## Population `order by` clause
Similarly to the `populateWhere`, you can also control the `order by` clause used for the populate queries. The default behaviour is to use the same ordering as for the root entity, and you can use `populateOrderBy` option to add a different ordering:
```ts
await em.find(Author, { ... }, {
populate: ['books'],
populateOrderBy: { books: { publishedAt: 'desc' } },
});
```