如何基于变量为嵌套文档动态设置mongodb字段名称?

时间:2015-07-06 02:44:31

标签: javascript mongodb meteor

我正在尝试将数据插入到Mongodb文档中,以便根据它的轮次使用Meteor编码的游戏。

我希望最终结果是这样的:

{
"room" : "TEST",
"createdAt" : ISODate("2015-07-05T22:04:47.931Z"),
"started" : true,
"round" : 2,
"players" : [
    {
        "userId" : "ASDF",
        "playerName" : "Ed"
    },
    {
        "userId" : "ZXCV",
        "playerName" : "Joe"
    }
],
"answers" : {
    "1": [
    {
        "userId" : "ASDF",
        "answer" : "asdf"
    },
    {
        "userId" : "ZXCV",
        "answer" : "adfafa"
    }],
    "2": [
    {
        "userId" : "ASDF",
        "answer" : "hello"
    },
    {
        "userId" : "ZXCV",
        "answer" : "hi"
    }]
  }
}

下面的javascript是针对提供findAndModify功能的Meteor包。这就是为什么语法与标准MongoDB略有不同,但它基本上解析了参数并向Mongo后端发送了一个正确的查询,因此最终结果与标准相同。我试图解决的部分是$ addToSet参数..

        result = Rooms.findAndModify({
            query: {
                players: {
                    $elemMatch: {
                        userId: userId
                    }
                }
            },
            update: {
                $addToSet: {
                    answers: {
                        round: { // Where round is substituted with "1", "2" etc
                            userId: userId,
                            answer: answer
                        }
                    }
                },
                $inc: {
                        count: 1
                    }
            },
            new: true
        });

我发现其他问题,人们基本上创建了一个占位符变量,并将值添加到其中,其结果如下:

var q = {};
q[round] = round;

update: { $addToSet: q }

然而,这仅适用于键值对。我想我需要得到类似的东西:

update: {
        $addToSet: 
        answers: {
            round: { // Where round is dynamically substituted with "1", "2" etc
                userId: userId,
                answer: answer
            }
        }
}

动态地如下:

update: {
        $addToSet: 
        answers: {
            "1": {
                userId: userId,
                answer: answer
            }
        }
}

我猜我必须使用我要插入的嵌套块构建一个JSON对象,但我不知道如何做到这一点?嵌套的结构让我很困惑。

更新

除了下面的fuzzybabybunny的回答之外,我正在阅读这篇文章http://www.jibbering.com/faq/faq_notes/square_brackets.html,这篇文章在另一篇文章中提到过,并提出了具有相同效果的文章。只是看待同样事情的另一种方式。

    var r = {}
    var t = {}
    t.userId = userId;
    t.answer = answer;
    r[round] = t;

    $addToSet: r

1 个答案:

答案 0 :(得分:0)

以编程方式为findAndModify创建整个参数:

// I'm assuming round, userId, and answer are defined somewhere already
// Create a function that returns an object with a custom keyname and value

var createObject = function(keyName, value){
  // I have this typeof check because key names cannot be an integer
  if(typeof keyName !== "string"){
    console.log("ERROR! keyName needs to be a string.");
  } else {
    var obj = {};
    obj[keyName] = value;
    return obj;
  }
};

var round = "3";

var userAndAnswer = {
  userId: "SDFSD",
  answer: "hello"
};

var findAndModifyArgument = {
  query: {
    players: {
      $elemMatch: {
        userId: userId
      }
    }
  },
  update: {
    $addToSet: {
      answers: createObject(round, userAndAnswer)
    },
    $inc: {
      count: 1
    }
  },
  new: true
};

// findAndModify is a function that takes a single object as an argument, 
// and that's what we created above
result = Rooms.findAndModify(findAndModifyArgument);