在mongoose中更新嵌套查询

时间:2015-02-11 17:38:34

标签: node.js mongodb 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: {}
});

我正在尝试更新timesAnswered中的QuestionsSchema属性。

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

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

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

我引用了这个问题,但我不知道为什么它不适合我。 Mongoose nested document update failing?

3 个答案:

答案 0 :(得分:1)

此查询应该完成您要执行的操作(您不需要find子句中的$):

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

  })

答案 1 :(得分:1)

您的代码有两个问题。

首先,正如@yazarubin指出的那样,您的更新条件有一个不必要的$,所以只需删除它:

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

其次,您在标准for(同步)内运行更新任务(异步任务),因此不会等待更新任务完成。在这种情况下,您可以使用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
});

,或者你可以使用某种promises库来完成同样的任务。

答案 2 :(得分:0)

你可以尝试:

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