我有一个包含User
对象的msg
集合。该对象包含两个属性:'unread'
和'blockedBy'
。 'unread'
属性为Number
类型,并保存用户当前拥有的未读邮件数量。
当用户调用消息收件箱服务(api/messages/inbox/:messageId
)时,我想在User
集合中减少此数字以保持同步。
我已经尝试过所有我能想到的事情。从使用User.update()
语句到User.findById(user.save())
到user.markModified('msg.unread')
,没有任何作用。
user.save()
上的回调显示预期结果,但数据未提交给MongoDB。
以下是代码:
User.findById(req.session.uid, function (err, user) {
if (err) {
return next(err);
}
user.msg.unread = user.msg.unread - 1;
//let mongoose know that this has been updated, so it will be committed to DB
user.markModified('msg');
user.save(function (err, user) {
if (err) {
return next(err);
}
message.read = true;
message.save(function (err, message) {
if (err) {
return next(err);
}
res.json({
'error': false,
'data': message
});
});
});
});
以下是用户模型的相关部分:
msg: {
unread: {type: Number, default: 0},
blockedBy: {type: Array}
},
答案 0 :(得分:0)
user.save()上的回调显示了预期的结果,但数据未提交给MongoDB。
这表示您已成功递减该值,但最有可能在稍后使用save
撤消该值。
例如,如果直接更新数据库而不是user
对象,然后保存user
对象,它将覆盖数据库中的整个用户对象并恢复为旧的未减少的值
答案 1 :(得分:0)
使用 async 模块简化此任务,特别是您需要使用 async.series()
,因为您要运行多项任务相互依赖,即在更新User
模型之前更新msg
模型的Message
对象:
var async = require("async"),
userId = req.session.uid,
locals = {};
async.series(
[
// Update user
function(callback) {
var update = { "$inc": { "msg.unread": -1 } },
query = { "_id": userId };
User.update(query, update, function (err, result) {
if (err) return callback(err);
callback();
});
},
// Modify message here (won't be called before task 1's "task callback" has been called)
function(callback) {
var update = { "$set": { "read": true } },
query = { "_id": messageId },
options = { "new": true }; //if true, return the modified document rather than the original. defaults to false
Message.findOneAndUpdate(query, update, options, function (err, message) {
if (err) return callback(err);
locals.data = message;
locals.error = false;
callback();
});
},
], function(err) { //This function gets called after the two tasks have called their "task callbacks"
if (err) return next(err);
//Here locals will be populated with 'data' and 'error'
res.json(locals);
}
);