猫鼬:使用-1

时间:2016-02-07 17:39:25

标签: mongodb mongoose

我有一个包含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}
},

2 个答案:

答案 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);
    }
);