使用mongoose在mongoDB中更新数组的数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用mongoose在mongoDB中更新数组的数组相关的知识,希望对你有一定的参考价值。

我正在尝试更新包含嵌套数组的mongoDB中的文档。 情况如下:

我有一个newsItem模型,它可以包含一个poll对象。此poll对象具有:title,totalVotes和options。 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 route / news / votes /:id时,它将使用:id更新newsitem并将用户id放在给定的voteoption中。 (在正文中)所以在请求中我有:用户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个选项:

  • 将整个poll对象提取到另一个文档然后使用newsItem中的引用..但是这也没有解决问题(也感觉到SQL)
  • 没有在每个投票选项中放置一系列投票用户,而只是制作所有投票人的用户数组。 - >缺点:我不能抬头谁投票什么..
答案

由于你并没有真正使用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(...)

以上是关于使用mongoose在mongoDB中更新数组的数组的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB(Mongoose)更新数组数组中的元素

如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?

Mongoose 不更新 mongodb 中的数组

如何使用 node 和 reactjs 向 mongoose 数组添加注释?

以角度(mongoose/mongodb)更新模型,特别是作为模型属性的对象数组

如何使用子文档数组更新 MongoDB 文档