添加到实例的特殊方法/mixins
当在两个模型之间创建关联时,这些模型将会被注入特殊的方法来对与其关联的模型进行交互。这些方法主要也是进行增删改查,具体会注入哪些方法由关联方式而定
一对一
现在又两个模型ClassModel表示班级,StudentModel表示学生
ClassModel.hasOne(StudentModel)
一对一,假设一个班级只有一个学生
- classModelInstance.getStudent():获取此数据关联的所有数据
- classModelInstance.setStudent():为已创建的数据设置关联
- classModelInstance.createStudent():为此数据创建关联数据
各方法解释
-
使用标准方式为两个模型创建数据
// 创建一个班级 const classData = await classModel.create({ name: "班级一" }); // 创建一个学生 const studentData = await studentModel.create({ name: "学生一", age: "18" }); // 通过关联后混入的方法,得到该条数据关联的学生 console.log(await classData.getStudent()); // null,因为此数据未关联任何学生 -
使用
set设置关联const classData = await classModel.create({ name: "班级一" }); const studentData = await studentModel.create({ name: "学生一", age: "18" }); // 设置关联 await classData.setStudent(studentData); console.log(await classData.getStudent()); // 学生一 -
使用
create直接创建关联数据const classData = await classModel.create({ name: "班级一" }); await classData.createStudent({ name: "学生一", age: "18" }); console.log(await classData.getStudent()); // 学生一 -
清空关联
// 传入null值即可清空其关联 classData.setStudent(null);
studentModel.belongsTo(classModel);
一个学生只能属于一个班级,所以也是一对一关系,拥有以上一致方法
studentModelInstance.getClass()studentModelInstance.setClass(()studentModelInstance.createClass(()
一对多
classModel.hasMany(studentModel); // 一个班级有多个学生
studentModel.belongsTo(classModel); // 一个学生只能属于一个班级
关联后会混入以下方法
classModelInstance.getStudents():获取该班级下所有学生classModelInstance.countStudents():获取该班级下的学生总数classModelInstance.hasStudent():该班级下是否有这个学生classModelInstance.hasStudents():该班级下是否有这些学生classModelInstance.setStudents(Model | string | [Model] | string[])classModelInstance.addStudent(Model | string | [Model] | string[]))`:将已有的学生添加进该班级classModelInstance.addStudents(Model | string | [Model] | string[]))`:将已有的学生们添加进该班级classModelInstance.removeStudent(Model | string | [Model] | string[]))`:删除这个学生classModelInstance.removeStudents(Model | string | [Model] | string[]))`:删除这些学生classModelInstance.createStudent(data):创建一个学生
方法解释
-
为班级添加学生
// 创建了一个班级 const classData = await classModel.create({ name: "班级一" }); // 创建了两个学生,此时这两个学生不属于任何班级 const studentData1 = await studentModel.create({ name: "学生一", age: 18 }); const studentData2 = await studentModel.create({ name: "学生二", age: 17 }); // 为班级添加这两个学生 await classData.addStudent(studentData1); await classData.addStudent(studentData2); console.log(await classData.getStudents()); // 学生一,学生二// 上面添加学生的方法也可以使用复数形式的方法,传递一个数组 await classData.addStudents([studentData1, studentData2]); // 其实 addStudent 与 addStudents 是一致的,但从语义上来说还是做一下区分 -
从班级里删除学生
const classData = await classModel.create({ name: "班级一" }); const studentData1 = await studentModel.create({ name: "学生一", age: 18 }); const studentData2 = await studentModel.create({ name: "学生二", age: 17 }); await classData.addStudents([studentData1, studentData2]); await classData.removeStudent(studentData1) console.log(await classData.getStudents());// remove 与 add 传递的参数一致,只不过意思相反 // 同样也可使用 removeStudents 删除多个学生 -
使用 create 直接创建学生,该方法一次只能创建一条数据
const classData = await classModel.create({ name: "班级一" }); await classData.createStudent({ name: "学生一", age: "18" }); console.log(await classData.getStudents()); // 学生一 -
清除关联数据,只是清空关联,并不是删除数据
await classData.setStudents([]);
getter方法接受选项,就像通常的查找器方法一样(比如findAll):
const easyTasks = await project.getTasks({
where: {
difficulty: {
[Op.lte]: 5,
},
},
});
const taskTitles = (
await project.getTasks({
attributes: ['title'],
raw: true,
})
).map(task => task.title);
多对多
多个老师可以教多个班级,多个班级也可以有多个老师
Foo.belongsToMany(Bar, { through: Baz })
多对多,一个Foo属于有个Bar
The same ones from Foo.hasMany(Bar):
fooInstance.getBars()fooInstance.countBars()fooInstance.hasBar()fooInstance.hasBars()fooInstance.setBars()fooInstance.addBar()fooInstance.addBars()fooInstance.removeBar()fooInstance.removeBars()fooInstance.createBar()
对于belongsToMany关系,默认情况下getBars()将返回连接表中的所有字段。请注意,任何include选项都将应用于目标Bar对象,因此不可能像使用find方法快速加载时那样尝试为连接表设置选项。为了选择要包含的连接表的属性,getBars()支持一个joinTableAttributes选项,该选项的使用方法与setting through类似。包含中的属性。作为一个例子,给定Foo belongsToMany Bar,下面将输出没有连接表字段的结果:
const foo = Foo.findByPk(id, {
include: [
{
model: Bar,
through: { attributes: [] },
},
],
});
console.log(foo.bars);
const foo = Foo.findByPk(id);
console.log(foo.getBars({ joinTableAttributes: [] }));
方法名称
如上例所示,Sequelize给这些特殊方法的名称是由一个前缀(例如get, add, set)与模型名称(第一个字母是大写的)连接而成的。必要时,使用复数形式,例如在fooInstance.setBars()中。同样,不规则复数也由Sequelize自动处理。例如,Person变成People, Hypothesis变成Hypothesis。
如果定义了别名,将使用它代替模型名来形成方法名。例如:
Task.hasOne(User, { as: 'Author' });
taskInstance.getAuthor()taskInstance.setAuthor()taskInstance.createAuthor()