我正在构建一个Web应用程序,我花了很长时间来处理相关文档之间的更新。
例如,我有"任务"文档和"用户"文档。完成任务后,将为其分配多个用户。因此
taskA.assigned = ["1321231fsdfsdf"(userA's _id), "12312313asdasdasd"(userB's _id)]
userA.tasks = [..., "1231321"(taskA's _id),...]
userB.tasks = [..., "12313211"(taskB's _id),...]
在创建任务时,我可以很好地处理它。但是,当我要编辑任务时,这变得太棘手了。如果从任务 A 中删除用户 B,我必须删除用户 B 的 ID 并转到用户 B 的任务属性并删除任务 A 的 ID。
有没有捷径和自动的方法来处理它?感谢您抽出宝贵时间阅读它。如果我太模糊,请告诉我,我会添加更多细节。
在像MySQL这样的关系数据库中,使用外键和级联更新可以自动完成,但在MongoDB中这是不可能的。
但是我在标签中看到您正在使用 Moongose,因此使用后期保存钩子可以解决问题。您可以设置一个挂钩,每次更新任务时自动更新用户集合,反之亦然。
另一种选择是更改您的数据结构,但这取决于您的情况,需要考虑一些事实。我认为我们没有足够的信息来判断,但是有很多资源在谈论MongoDB中的数据规范化,例如可以查看官方的MongoDB手册。
我找到了一种轻松做到这一点的方法,而且代码行更少。通过这样做,大约 100 行减少到大约 30 行。
长话短说,我使用了"update()"方法和各种mongo运算符,例如$in,$push或$pull。
这是我使用更新方法优化的最终代码。
var edit = req.body;
edit.assignedTo = edit.assignedTo.split(',');
var old = req.task;
var idQueries = edit.assignedTo.map(function (x) {
return mongoose.Types.ObjectId(x);
});
User.update({tasks: old._id}, {$pull: {tasks: old._id}}, {multi: true}, function () {
// Update to remove original task's id from users assigned to it.
User.update({_id: {$in: idQueries}}, {$push: {tasks: old._id}}, {multi: true}, function () {
// Update to add edited tasks'id to new users assigned to it.
old.lastAction = 'edited';
old.edited = true;
old.editedAt = Date.now();
old.titke = edit.title;
old.desc = edit.desc;
old.dueBy = edit.dueBy;
old.assignedTo = edit.assignedTo;
old.save(function (err, task) {
if (err) return next(err);
User.populate(task, 'assignedTo', function (err, task) {
res.json(task);
});
});
});
});
希望这对某些人有所帮助!