更新参考以及其他值Mongoose

时间:2016-04-01 06:52:32

标签: node.js mongodb mongoose

这是我正在处理的架构。

var testSchema = mongoose.Schema({ 
    userCreated : {
        type :  mongoose.Schema.Types.ObjectId,
        ref : "User"
    },
    points : {type: Number, default: 0},
    numVotes : {type: Number, default: 0},
    createdAt : Date,
    updatedAt : Date,
}, { timestamps : true });

现在,我正在尝试编写一个函数,该函数将增加此文档(pointsnumVotes上的两个字段,以及用户模式上存在的其他points字段

这是我的尝试。

testSchema.statics.incrementTest = function(id, ...) {
    this.findByIdAndUpdate(id, {$inc : {
        points : 5, 
        numVotes : 1, 
        'userCreated.points' : 5
    }}).exec();
}

现在,我写的这段代码不起作用。但是,当我注释掉'userCreated.points' : 5行时,其他两个字段会按预期增加。我的问题是,使用mongoose同时更新文档中的字段和子文档上的字段的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

此处的数据包含在不同的集合中,因此没有一个update语句能够同时增加两个计数器。

为了获得一致的视图,您需要"链"您的更新语句并使用每个语句的返回结果来构建响应。

根据您的需要,您可以使用Promise

testSchema.statics.incrementTest = function(id) {
  var self = this;
  return new Promise(function(resolve,reject) {
    self.findByIdAndUpdate(
      id,
      {
        "$inc": {
          "points": 5,
          "numVotes": 1
        }
      },
      { "new": true }
    ).then(function(test) {
      var userModel = test.schema.path("userCreated").options.ref;
      mongoose.model(userModel).findByIdAndUpdate(
        test.userCreated,
        { "$inc": { "points": 5 } },
        { "new": true }
      ).then(function(user) {
        test.userCreated = user;
        resolve(test);
      })
    }).catch(reject)
  })
};

然后您可以在模型上调用:

Test.incrementTest("56fe279d363ce91765d9e39e").then(function(test) {
    console.log(JSON.stringify(test,undefined,2));
}).catch(function(err) {
    throw err;
})

如果您更适合,可以使用async.waterfall库中的async

testSchema.statics.incrementTest = function(id,callback) {
  var self = this;

  async.waterfall(
    [
      function(callback) {
        self.findByIdAndUpdate(
          id,
          { 
            "$inc": {
              "points": 5,
              "numVotes": 1
            }
          },
          { "new": true },
          callback
        )
      },
      function(err,test) {
        if (err) callback(err);
        var userModel = test.schema.path("userCreated").options.ref;
        mongoose.model(userModel).findByIdAndUpdate(
          test.userCreated,
          { "$inc": { "points": 5 } },
          { "new": true },
          function(err,user) {
            if ( typeof(user) !== "undefined" )
                test.userCreated = user;
            callback(err,test);
          }
        );
      }
    ],
    callback
  );
};

具有类似用法:

Test.incrementTest("56fe279d363ce91765d9e39e",function(err,test) {
    if (err) throw err;
    console.log(JSON.stringify(test,undefined,2));
})

两者都应该给你一个结果,显示两个集合中两个对象的增量数据:

{ points: 5,
  numVotes: 1,
  __v: 0,
  userCreated: { points: 5, __v: 0, _id: 56ff1aa6dba6d13e798fc894 },
  createdAt: Sat Apr 02 2016 12:04:38 GMT+1100 (AEDT),
  updatedAt: Sat Apr 02 2016 12:04:38 GMT+1100 (AEDT),
  _id: 56fe279d363ce91765d9e39e }