【问题标题】:Updating an array of an array in mongoDB using mongoose使用 mongoose 在 mongoDB 中更新数组的数组
【发布时间】:2018-10-06 00:54:55
【问题描述】:

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

我有一个 newsItem 模型,它可以包含一个 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 路由 /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 个选项:

  • 将整个投票对象提取到另一个文档,然后使用 在 newsItem 中引用 .. 但这并不能解决问题 要么(对 SQL 也有感觉)
  • 不将投票用户数组放入每个投票选项中,而只是让 所有投票的人的用户数组。 --> 缺点:我不能看 谁对什么投了赞成票..

【问题讨论】:

    标签: javascript node.js mongodb mongoose mongoose-schema


    【解决方案1】:

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

    【讨论】:

    • 这完美!我选择使用第二个选项,因为它与我的其他代码一起感觉更直观。我现在通过查看您的示例更好地了解了如何查询。谢谢!
    猜你喜欢
    • 2020-04-18
    • 2022-01-22
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 2018-02-21
    • 2018-02-05
    相关资源
    最近更新 更多