我有两个模型技能和课程。每当我更新任何现有技能名称时,我希望它更新课程对象中的技能名称,该对象已经拥有这些技能。
当我更新任何技能时,如何自动更新course.skills
中的技能名称?
课程模型:
const courseSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
},
description: {
type: String,
},
skills: [
{
name: { type: String },
id: { type: mongoose.Schema.Types.ObjectId, ref: 'Skill' },
},
],
}
);
技能模型:
const Course = require('./course.model');
const skillSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
},
description: {
type: String,
},
points: {
type: Number,
},
},
{
timestamps: true,
}
);
这是更新技能的函数:
module.exports.updateSkillById = async (req, res) => {
const updates = Object.keys(req.body);
const allowedUpdates = ['name', 'description', 'points'];
const isValidOperation = updates.every((update) =>
allowedUpdates.includes(update)
);
if (!isValidOperation) {
return res.status(400).send({ error: 'Invalid updates!' });
}
try {
const skill = await Skill.findOneAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true,
});
if (!skill) {
return res.status(404).send();
}
res.send(skill);
} catch (err) {
res.status(400).send(err);
}
};
实现这一目标的一种方法是使用Mongoose中间件函数。你可以使用pre('findOneAndUpdate)挂钩技能模型
这将在更新技能对象之前触发。
在钩子中,你可以用一个事务手动更新你的课程。
skillSchema.pre('findOneAndUpdate', async function(next) {
const skill = this.getUpdate();
const courses = await Course.find({ 'skills.id': skill._id });
if (courses.length > 0) {
try {
const session = await mongoose.startSession();
session.startTransaction();
for (let i = 0; i < courses.length; i++) {
const course = courses[i];
const skillIndex = course.skills.findIndex(s => s.id.equals(skill._id));
if (skillIndex >= 0) {
course.skills[skillIndex].name = skill.name;
await course.save({ session });
}
}
await session.commitTransaction();
} catch (err) {
await session.abortTransaction();
throw err;
}
}
next();
});
我正在使用save()方法解决这个问题。使用save()
方法代替findByIdAndUpdate()
方法将返回prehook中更新的对象。
更新函数如下:
const skill = await Skill.findById(req.params.id);
if (!skill) {
return res.status(404).send();
}
updates.forEach((update) => (skill[update] = req.body[update]));
await skill.save();
预钩子为:
skillSchema.pre('save', async function (next) {
const skill = this;
const courses = await Course.find({ 'skills.id': skill._id });
await updateModel(courses, skill, 'skills');
if (courses.length > 0) {
await Promise.all(
courses.map((course) => {
const skillIndex = course.skills.findIndex((sk) =>
sk.id.equals(skill._id)
);
course.skills[skillIndex].name = skill.name;
return course.save();
})
);
}
next();
});