这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战
预先加载
预先加载是一次查询多个模型的数据的行为,是具有一个或多个 join 的查询
const User = sequelize.define('user', { name: DataTypes.STRING }, { timestamps: false });
const Task = sequelize.define('task', { name: DataTypes.STRING }, { timestamps: false });
const Tool = sequelize.define('tool', {
name: DataTypes.STRING,
size: DataTypes.STRING
}, { timestamps: false });
User.hasMany(Task);
Task.belongsTo(User);
User.hasMany(Tool, { as: 'Instruments' });
获取单个关联元素
关联的用户加载所有任务
const tasks = await Task.findAll({ include: User });
console.log(JSON.stringify(tasks, null, 2));
打印结果:
[{
"name": "A Task",
"id": 1,
"userId": 1,
"user": {
"name": "张三",
"id": 1
}
}]
总结:
关联的模型被添加到名为 user
的新字段中. Sequelize 会根据关联模型的名称自动选择此字段的名称,在适用的情况下(即关联为 hasMany
或 belongsToMany
)使用该字段的复数形式
获取所有关联的元素
const users = await User.findAll({ include: Task });\
console.log(JSON.stringify(users, null, 2));
打印结果:
[{
"name": "张三",
"id": 1,
"tasks": [{
"name": "A Task",
"id": 1,
"userId": 1
}]
}]
关联是一对多的,因此访问器(结果实例中的tasks
属性)是复数的
获取别名关联
如果关联是别名的(使用as
参数),则在包含模型时必须指定此别名,但可以为对象提供两个选项:model
和 as
const users = await User.findAll({
include: { model: Tool, as: 'Instruments' }
});
console.log(JSON.stringify(users, null, 2));
打印结果:
[{
"name": "张三",
"id": 1,
"Instruments": [{
"name": "hammer",
"id": 1,
"userId": 1
}]
}]
也可以指定的关联别名相匹配的字符串
User.findAll({ include: 'Instruments' }); // 也可以正常使用
User.findAll({ include: { association: 'Instruments' } }); // 也可以正常使用
需要预先加载
预先加载时,可以强制查询仅返回具有关联模型的记录,通过 required: true
参数将查询从默认的 OUTER JOIN
转为 INNER JOIN
User.findAll({
include: {
model: Task,
required: true
}
});
在模型级别的预先加载加入过滤
预先加载时, 可以使用 where
参数过滤关联的模型
User.findAll({
include: {
model: Tool,
as: 'Instruments'
where: {
size: {
[Op.ne]: 'small'
}
}
}
});
模型中应用 WHERE
子句来引用关联模型中的值,可以使用 Sequelize.col
函数
// 查找所有具有至少一项任务的项目,其中 task.state === project.state
Project.findAll({
include: {
model: Task,
where: {
state: Sequelize.col('project.state')
}
}
})
加入复杂的 where 子句
嵌套列的顶级 WHERE
子句, Sequelize 引用嵌套列的方法:'$nested.column$'
, 可以用于将 where
条件从包含的模型从 ON
条件移动到顶层的 WHERE
子句
User.findAll({
where: {
'$Instruments.size$': { [Op.ne]: 'small' }
},
include: [{
model: Tool,
as: 'Instruments'
}]
});
使用带有 include 的 findAndCountAll
findAndCountAll
实用功能支持 include. 仅将标记为 required
的 include 项视为 count
User.findAndCountAll({
include: [
{ model: Profile, required: true }
],
limit: 3
});
因为 Profile
的 include 已设置为 required
,它将导致内部联接,并且仅统计具有个人资料的用户,如果从包含中删除 required
,则包含和不包含配置文件的用户都将被计数. 在 include 中添加一个 where
子句会自动使它成为 required
User.findAndCountAll({
include: [
{ model: Profile, where: { active: true } }
],
limit: 3
});
上面的查询只会统计拥有有效个人资料的用户, 因为在 include
中添加 where
子句时,required
会隐式设置为 true