关系加载策略
MikroORM 支持两种加载策略:
¥MikroORM supports two loading strategies:
-
select-in
对每个关系使用单独的查询 - 如果你填充两个关系,你将获得三个查询 - 一个用于根实体,另一个用于每个填充关系。¥
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
使用单个查询并连接关系。¥
joined
which uses a single query and joins the relations instead.
joined
策略仅在 SQL 驱动程序中受支持,并且是自 v6 以来的默认策略。¥
joined
strategy is supported only in SQL drivers and is the default for those since v6.
配置策略
¥Configuring the strategy
加载策略可以在映射时和加载实体时指定,也可以在 ORM 配置中全局指定。
¥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:
import { Entity, LoadStrategy, OneToMany, ManyToOne, PrimaryKey } from '@mikro-orm/core';
@Entity()
export class Author {
@PrimaryKey()
id!: number;
@OneToMany(() => Book, b => b.author)
books = new Collection<Book>(this);
}
@Entity()
export class Book {
@PrimaryKey()
id!: number;
@ManyToOne()
author: Author;
}
使用默认的 joined
策略,这将对 Author
实体及其 books
关系发出单个查询。
¥With the default joined
strategy, this will issue a single query both the Author
entity and its books
relation.
const author = await orm.em.findOne(Author, 1, {
populate: ['books'],
});
要覆盖策略,你可以使用 strategy
选项:
¥To override the strategy, you can use the strategy
option:
const author = await orm.em.findOne(Author, 1, {
populate: ['books'],
strategy: 'select-in',
});
这将发出两个 SQL 语句,一个用于加载作者,另一个用于加载属于该作者的所有书籍:
¥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.
import { Entity, LoadStrategy, OneToMany } from '@mikro-orm/core';
@Entity()
export class Author {
// ...
@OneToMany({
entity: () => Book,
mappedBy: b => b.author,
strategy: 'select-in', // force select-in strategy for this relation
})
books = new Collection<Book>(this);
}
在属性级别定义的策略将始终优先。
¥The strategy defined on property level will always take a precedence.
全局更改加载策略
¥Changing the loading strategy globally
你可以在 ORM 配置中使用 loadStrategy
选项:
¥You can use loadStrategy
option in the ORM config:
MikroORM.init({
// ...
populate: ['books'],
loadStrategy: 'select-in', // 'joined' is the default for SQL drivers
});
此值将用作默认值,在属性级别指定加载策略具有优先权,并在 FindOptions
中指定它。
¥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
条件
¥Population where
condition
默认情况下,where 条件仅适用于根实体。这可以通过 populateWhere
选项进行控制。它接受 all
(默认)、infer
(使用与 where
查询相同的条件)或显式过滤查询之一。
¥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.
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
也可以全局设置,默认值为all
。¥
populateWhere
can be also set globally, the default isall
.
Population order by
子句
¥Population order by
clause
与 populateWhere
封装器类似,我们也可以将带有 order by
的标量封装到 对象中。默认行为是使用与根实体相同的顺序,你可以使用 populateOrderBy
选项添加不同的顺序:
¥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:
await em.find(Author, { ... }, {
populate: ['books'],
populateOrderBy: { books: { publishedAt: 'desc' } },
});