2016-04-01 17 views
0

ここには私が取り組んでいるスキーマがあります。他の値と一緒に参照を更新する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フィールド上の2つのフィールドをインクリメントする関数を記述しようとしています。

ここに私がいます試み。

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

さて、私が書いたこのコードは動作しません。しかし、私は'userCreated.points' : 5行をコメントアウトすると、期待どおり、他の2つのフィールドがインクリメントを行う。マイ質問は、ドキュメントのフィールドとサブフィールドのフィールドを同時に更新するために、mongooseを使用する最善の方法は何ですか?

+0

種類が実際として格納されていないref'マングース '同様の用法を持っていドキュメントには、オブジェクトIDだけが格納されます。したがって、パス 'userCreated.points'はtestSchemaに存在しないため、更新できません。ユーザー文書を更新するために別の更新クエリを実行する必要があります。 –

答えて

1

ここでのデータはさまざまなコレクションに含まれているため、1つの更新ステートメントで両方のカウンターを同時にインクリメントすることはできません。

一貫性のあるビューを得るには、更新ステートメントを「連鎖」し、それぞれの返信結果を使用してレスポンスを構築する必要があります。

ニーズに応じて、あなたはこれでPromiseを使用することができ、次のいずれか

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

場合や、asyncライブラリからasync.waterfallを使用することができます:あなたは、あなたのモデルに呼び出すことができ

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

をそれはあなたによく合います:

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 } 
関連する問題