如何更新mongoose文档时如何触发函数

时间:2017-03-30 17:15:23

标签: node.js mongoose mongoose-schema

我在mongoose中有一个用户模型架构,其中包含朋友和群组列表以及stats信息,如此...

var user = new Schema({
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true, select: false },
  roles: [{ type: String, required: true }],
  friends: [{ type: Schema.Types.ObjectId, ref: 'User' }],
  groups: [{ type: Schema.Types.ObjectId, ref: 'Group' }], 
  stats : {
    nbrFriends: { type: Number, required: false },
    nbrGroups: { type: Number, required: false }
  }
}, {
  timestamps: true
}); 

每当对statsfriends字段进行更改以包含新的groupsfriends时,我都需要更新用户groups例如,当在用户上调用以下函数时:

var addGroup = function(user, group, cb) {

  user.groups.push(group);
  User.findOneAndUpdate({ _id: user._id }, { $set: { groups: user.groups }}, { new: true }, function(err, savedResult) {
    if(err) {
      return cb(err);
    }
    console.log('updated user: ' + JSON.stringify(savedResult));
    return cb(null, savedResult);
  });
};

如何确保stats自动更新为包含用户拥有的新号码groups?看起来中间件功能似乎是最好的方法。我试过以下但是这似乎永远不会被称为......

user.pre('save', function(next) {
  var newStats = {
    nbrGroups: this.groups.length,
    nbrPatients: this.friends.length
  };
  this.stats = newStats;
  this.save(function(err, result) {
    if(err) {
      console.log('error saving: ' + err);
    } else {
      console.log('saved');
    }
    next();
  });  
});

3 个答案:

答案 0 :(得分:2)

您需要使用中间件a.k.a. hooks:

  

中间件(也称为前后挂钩)是在异步函数执行期间传递控制的函数。

参见文档:

答案 1 :(得分:1)

version 3.6中,您可以使用change streams

赞:

const Users = require('./models/users.js')

 var filter = [{
        $match: {
            $and: [{
                 $or:[
                { "updateDescription.updatedFields.friends": { $exists: true } },
                { "updateDescription.updatedFields.groups": { $exists: true } },
              ]
                { operationType: "update" }]
            }
        }];

 var options = { fullDocument: 'updateLookup' };


let userStream = Users.watch(filter,options)

userStream.on('change',next=>{

//Something useful!

})

答案 2 :(得分:0)

您应该使用Vanilla JS进行更新,然后保存更新后的文档以触发预保存的挂钩。

请参见Mongoose docs

如果要更新的键很多,则可以遍历正文中的键并逐个更新。

const user = await User.findById(id);

Object.keys(req.body).forEach(key => {
  user[key] = req.body[key];
}

const saved = await user.save();