更新mongoose中的嵌套查询

我从最近2小时挣扎更新我的嵌套集合。 有人可以尝试引导我正确的方向吗?

var ChoiceSchema = new Schema ({ body: {type: String, required: true}, correct: {type: Boolean, required: true}, timesDisplayed: {type: Number, default: 0}, timesSelected: {type: Number, default: 0}, images: {} }); var QuestionSchema = new Schema({ contentId: {type: String, required: true}, questionBody: {type: String, required: true}, timesAnswered: {type: Number, default: 0}, timesCorrect: {type: Number, default: 0}, timesIncorrect: {type: Number, default: 0}, timesSkipped: {type: Number, default: 0}, explanation: { contentId: {type: String, required: true}, body: {type: String, required: true}, images: {} }, images: {}, choices: [ChoiceSchema] }); var ExamSchema = new Schema ({ subject: {type: String, required: true}, dateCreated: { type: Date, default: Date.now }, examNumber: Number, section1: { part1: { timeInMinutes: Number, instructions: {type: String, required: true}, questions: [QuestionSchema] }, part2: {} }, section2: {} }); 

我正在尝试更新QuestionsSchematimesAnswered属性。

  Exam.findById(req.params.id, function (err, exam) { var ids=JSON.parse(req.body.ids); if(err) { return handleError(res, err); } if(!exam) { return res.send(404); } if(ids.length) { for(var i=0;i<ids.length;++i){ Exam.update({'section1.part1.questions.$._id':ids[i]}, { $set: { 'section1.part1.questions.$.timesAnswered': 1 // <== and here }}, function (err, numAffected) { if(err) throw err; } ); } } return res.json(exam); }); 

其中ids是包含问题ID的数组

 [ '54db8ee6529b197018822eb4', '54db8ee6529b197018822ea7', '54db8ee6529b197018822ea0' ] 

我引用这个问题,但我不知道为什么它不为我工作。 Mongoose嵌套文件更新失败?

你的代码有两个问题。

首先, @ yazarubin指出,你的更新条件有一个不必要的$ ,所以只是删除它:

 Exam.update({'section1.part1.questions._id':id}, 

其次,你正在运行一个更新任务(asynchronous任务),在(同步)的标准内,所以它不会等待更新任务完成。 在这种情况下,您可以使用async.each函数:

 var async = require('async'); // be sure to install and require the async module async.each(ids, function (id, callback) { Exam.update({'section1.part1.questions._id':id}, { $set: { 'section1.part1.questions.$.timesAnswered': 1 // <== and here }}, function (err, numAffected) { if(err) throw err; callback(); } ); }, function (error) { if (error) res.send(500); res.send(exam); // send the response just when all tasks has finished }); 

,或者你可以使用某种承诺库来完成这个相同的任务。

这个查询应该完成你想要做的事情(你不需要find子句中的$):

 Exam.update({'section1.part1.questions._id':ids[i]}, { $set: { 'section1.part1.questions.$.timesAnswered':1 }}, function(err, numAffected){ }) 

你能试一下吗:

 Exam.findById(req.params.id, function (err, exam) { var ids=JSON.parse(req.body.ids); if(err) { return handleError(res, err); } if(!exam) { return res.send(404); } if(ids.length) { for(var i=0;i<ids.length;++i){ var question=exam.section1.part1.questions.id(ids[i]); question.timesAnswered=1; } exam.save(function(err) { if(err) throw err; }); } return res.json(exam); });