【问题标题】:MongoDb NodeJS driver findOneAndUpdate not working atomicallyMongoDb NodeJS 驱动程序 findOneAndUpdate 不能以原子方式工作
【发布时间】:2017-09-04 13:36:44
【问题描述】:

我有一个函数应该通过“ID”从 mongo 数据库中找到一个问题并返回它,如果它没有找到一个它创建一个然后返回它。它是我的代码中唯一能够在数据库中创建新问题实体的函数。这里是: (顺便说一句,我正在为 nodeJs 使用官方的 MongoDb 驱动程序)

function getQuestionEntity(questionID, cb){
    const questions = db.collection('questions')

    questions.findOneAndUpdate(
        {ID: questionID},
        {$setOnInsert: 
            {
                ID: questionID,
                rating: 1.5,
                options: 4,
                answeredRight: 0,
                answeredWrong: 0

            }
        },
        {
            returnOriginal: false,
            upsert: true
        },
        (err, r)=>{
            if(err){throw new Error(err)}
            cb(r.value)
        }
    )
}

我读到 findOneAndUpdate 是一个原子操作,这意味着即使我异步循环这个函数到时间结束,我仍然不会在数据库中获得两个具有相同“ID”字段的问题实体,但是这正是发生的事情。

我的代码有什么问题吗?我的假设错了吗?

【问题讨论】:

  • 更新操作是原子的,但 upsert 不是。见here。所以需要给ID添加唯一索引,然后在出现重复键错误时进行处理。

标签: node.js mongodb


【解决方案1】:

不要将文档的 id 设置两次,那么你会以这样的方式结束:

 questions.findOneAndUpdate(
   {ID: questionID},
   {$set: {rating: 1.5, options: 4, answeredRight: 0, answeredWrong: 0}}, 
   {upsert: true},
    (err, r)=>{
        if(err){throw new Error(err)}
        cb(r.value)
    }
   )

我没有在nodejs中测试过这段代码;不要使用 $setOnInsert,因为它只在插入时有效,并且在文档已经存在时不会更新键。

【讨论】:

  • 我插入的 id 是我从不同的数据库中获得的,如果它已经存在,我也不想更新。
猜你喜欢
  • 2017-03-05
  • 2016-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 2014-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多