Mongoose更新嵌套对象 - 异常:在路径'...'中找到太多位置(即'$')元素

时间:2016-06-24 18:12:11

标签: mongodb mongoose

我有这个架构定义:

mongoose.model('User', new Schema({
        provider_id: String,
        name: String,
        email: String,
        avatar: String,
        level: Number,
        score: Number,
        progress: {
             levels: { 'type' : Array , 'default' : [] }
        }
}))

我在数据库中有这样的文件

{
     "_id": "987765692e7687c6b123123",
     "provider_id": "1231231230324",
     "name": "Jas Mad",
     "email": "proba2@test.com",
     "avatar": "proba2.jpg",
     "level": 1,
     "score": 0,
     "progress": {
         "levels": [
              {
                 "_id": "576c888362024585bc5faab8",
                 "categories": [
                     {
                         "_id": "576c888362024585bc5faab9",
                         "questions": [
                             {"_id": "576c888362024585bc5faaba"}, 
                             {"_id": "576c888362024585bc5faabe"}, 
                             {"_id": "576c888362024585bc5faac2"}, 
                             {"_id": "576c888362024585bc5faac6"}, 
                             {"_id": "576c888362024585bc5faaca"}
                         ]
                     }, 
                     {
                         "_id": "576c888362024585bc5faace",
                         "questions": [
                             {"_id": "576c888362024585bc5faacf"}, 
                             {"_id": "576c888362024585bc5faad3"}, 
                             {"_id": "576c888362024585bc5faad7"}, 
                             {"_id": "576c888362024585bc5faadb"}, 
                             {"_id": "576c888362024585bc5faadf"}
                         ]
                     }
                 ]
             }
         ]
     },
     "__v": 0
 }

给定参数:userId,categoryId,questionId,optionId

我想要的是更新与{ “_ id”匹配的问题数组中的对象:questionId }添加属性{“selectedOption”:optionId}

像这样:

var setQuestionAnswer = function (data)
{
    var promise = new Promise(
            function (resolve, reject) {
                if (!data.levelId ||
                        !data.categoryId ||
                        !data.questionId ||
                        !data.optionId ||
                        !data.userId)
                {
                    reject({status:401, message: "Bad Request"});
                }
                User.findOneAndUpdate(
                    {
                        '_id': data.userId,
                        'progress.levels._id': data.levelId,
                        'progress.levels.categories._id': data.categoryId,
                        'progress.levels.categories.questions._id': data.questionId,
                        'progress.levels.$.categories.$.questions.$.selectedOption': {$exists: false}
                    },
                    {
                        $set: {"progress.levels.$.categories.$.questions.$.selectedOption":data.optionId}
                    },
                    {new:true},
                    function(err, user){
                        if(err)
                        {
                            reject(err);
                        }
                        else
                        {
                            resolve(user);
                        }
                    });
            });
    return promise;
};

当我运行此代码时,我从mongo收到错误:

exception: Too many positional (i.e. '$') elements found in path 'progress.levels.$.categories.$.questions.$.correct'

如果我使用零指数代替 $ ,例如“progress.levels.0.categories.0.questions.0.selectedOption”,我可以成功修改首先尝试,但后来再也不会工作了。如何使用 $ 之类的通配符使此更新适用于数组中的每个问题?

我正在尝试像这样更新用户文档

    {
     "_id": "987765692e7687c6b123123",
     "provider_id": "1231231230324",
     "name": "Jas Mad",
     "email": "proba2@test.com",
     "avatar": "proba2.jpg",
     "level": 1,
     "score": 0,
     "progress": {
         "levels": [
              {
                 "_id": "576c888362024585bc5faab8",
                 "categories": [
                     {
                         "_id": "576c888362024585bc5faab9",
                         "questions": [
                             {
                                 "_id": "576c888362024585bc5faaba",
                                 "selectedOption":"12312312312312312312"
                             }, 
                             {"_id": "576c888362024585bc5faabe"}, 
                             {"_id": "576c888362024585bc5faac2"}, 
                             {"_id": "576c888362024585bc5faac6"}, 
                             {"_id": "576c888362024585bc5faaca"}
                         ]
                     }, 
                     {
                         "_id": "576c888362024585bc5faace",
                         "questions": [
                             {"_id": "576c888362024585bc5faacf"}, 
                             {"_id": "576c888362024585bc5faad3"}, 
                             {"_id": "576c888362024585bc5faad7"}, 
                             {"_id": "576c888362024585bc5faadb"}, 
                             {"_id": "576c888362024585bc5faadf"}
                         ]
                     }
                 ]
             }
         ]
     },
     "__v": 0
 }

问候和感谢。

1 个答案:

答案 0 :(得分:1)

我实现了解决问题

var setQuestionAnswer = function (data)
{
    var promise = new Promise(
            function (resolve, reject) {
                debug('setQuestionAnswer');
                if (!data.levelId ||
                        !data.categoryId ||
                        !data.questionId ||
                        !data.optionId ||
                        !data.userId)
                {
                    reject({status: 401, message: "Bad Request"});
                    return;
                }
                User.findOneAndUpdate(
                    {
                        '_id': data.userId,
                        'progress.levels._id': data.levelId,
                        'progress.levels.categories._id': data.categoryId,
                        'progress.levels.categories.questions._id': data.questionId,
                        'progress.levels.categories.questions.selectedOption': { $exists:false }
                    },
                    {
                        $set:{ 'progress.levels.0.categories.0.questions.0.selectedOption': data.optionId }
                    })
                    .exec(function(err,user){
                        if (err)
                        {
                            reject(err);
                        } 
                        else
                        {
                            resolve(user);
                        }
                    });
            });
    return promise;
};

查找条件对象:

{
    '_id': data.userId,
    'progress.levels._id': data.levelId,
    'progress.levels.categories._id': data.categoryId,
    'progress.levels.categories.questions._id': data.questionId,
    'progress.levels.categories.questions.selectedOption': { $exists:false }
}

使用dot-notation过滤数据库中的文档

更新对象:

{
    $set:{ 'progress.levels.0.categories.0.questions.0.selectedOption': data.optionId }
}

由于预期查询只返回一个文档,我使用零索引来访问所需的嵌套对象并添加selectedOption属性