我正在尝试更新mongoDB中包含嵌套数组的文档。
情况如下:
我有一个newsItem模型,该模型可以包含一个轮询对象。此民意调查对象具有:标题,totalVotes和选项。 option是一个对象数组,这些对象包含:optionName和optionVotes。在每个这些对象中。 optionVotes是一个数组,其中包含对其进行投票的用户的ID。 (因为我想跟踪谁对什么以及我想防止两次投票进行表决)
所以它应该看起来像这样:
{
"_id" : ObjectId("5bb7487727430319f5c18495"),
"poll" : {
"totalVotes" : 0,
"title" : "test",
"options" : [
{
"optionName" : "Burgers",
"optionVotes" : []
},
{
"optionName" : "Pizza",
"optionVotes" : []
},
{
"optionName" : "Fish",
"optionVotes" : []
},
{
"optionName" : "BBQ",
"optionVotes" : []
},
{
"optionName" : "Soup",
"optionVotes" : []
},
{
"optionName" : "Pasta",
"optionVotes" : []
}
]
}
}
我现在想做的是,每当调用api路由/ news / votes /:id时,它将使用:id更新newsitem并将用户id放入给定的表决选项中。 (在体内) 因此,在请求中,我有:用户ID和投票的optionName
这是我目前无法使用的内容:
exports.vote = (req, res) => {
News.findOneAndUpdate({ _id: req.params.id }).exec((err, newsItem) => {
let tempItem = newsItem
for (let i = 0; i < tempItem.poll.options.length; i++) {
if (tempItem.poll.options[i].optionName === req.body.optionName) {
tempItem.poll.options[i].optionVotes.push(req.user._id)
}
}
console.log(tempItem.poll.options[0])
tempItem.save(err => {
if (!err) {
return res.status(200).send()
}
})
})
}
例如,当我这样做时,很奇怪:
tempitem.poll.title ='新标题' tempitem.save()
然后标题在数据库中得到更新! 代码中的console.log确实会输出正确的对象。
我也尝试使用更标准的方式:
findOneAndUpdate({ _id: req.param.id }, {$addToSet: {.....}}).exec(...)
但是我实际上不知道如何从数组中获取具有特定键的对象,然后更新该对象的一部分。
我正在考虑的其他2种选择:
答案 0 :(得分:0)
由于您并未真正使用findOneAndUpdate(因为您未提供实际的更新),因此您可以简单地使用findOne
并尝试执行以下操作:
exports.vote = (req, res) => {
News.findOne({ _id: req.params.id }).exec(err, tempItem) => {
let option = tempItem.poll.options.find(({optionName}) => optionName == req.body.optionName)
option.optionVotes.push(req.user._id)
console.log(option)
tempItem.save(err => {
if (!err) {
return res.status(200).send()
}
})
}
}
那是做到这一点的一种方法。我认为最好的方法是利用update
部分,并将findOneAndUpdate
与传入的更新对象一起使用。
像这样:
findOneAndUpdate({
_id: req.param.id, 'poll.options.optionName': req.body.optionName
},
{ $addToSet:
{ 'poll.options.$.optionVotes': req.user._id }
}).exec(...)