node.js - MongoDB:处理自动递增的模型 id 而不是 Mongo 的 native ObjectID

标签 node.js mongodb mongoose

由于管理决策,我们将 userId 用于用户集合,postId 用于帖子集合,topicId 用于主题集合,而不是每个集合的“_id”作为唯一标识符。

这会导致一些问题开始 - 我遇到的问题之一是 upserts -

使用 Mongoose,我们有一个架构将 userId 限制为唯一值 - 但是在更新用户模型时,将 upsert 设置为 true,MongoDB 似乎只查看 ObjectId集合来查看是否存在相同的集合 - 它不检查是否已经存在具有相同 userId 的模型 - 因此 Mongo 执行插入而不是更新。

让我用一些数据来说明这一点:

假设用户的集合有一个文档:

{
_id:'561b0fad638e99481ab6d84a'
userId:3,
name:'foo'
}

然后我们运行:

User.update({userId:3},{"$set":{name:'bar'},{upsert:true},function(err,resp){

if(err){

   // "errMessage": "insertDocument :: caused by :: 11000 E11000 duplicate key error index: app42153482.users.$userId_1  dup key: { : 3 }",
}

});

有人会认为 MongoDB 会找到带有 userId:3 的现有文档并更新它,所以一定是我做错了什么,因为它给了我重复键错误?

最佳答案

通常,默认值 ObjectId 更适合 _id。在这里,在这种情况下,您可以覆盖默认的 _id,也可以拥有自己的 id 字段(如您的情况下的 userId)。

使用单独的计数器集合来跟踪最后使用的数字序列。 _id 字段包含序列名称,seq 字段包含序列的最后一个值。

插入counters集合,userid的初始值:

db.counters.insert(    {
      _id: "userid",
      seq: 0    } )

创建一个接受序列名称的getNextSequence 函数。该函数使用 findAndModify() 方法以原子方式递增 seq 值并返回这个新值:

function getNextSequence(name) {
   var ret = db.counters.findAndModify(
          {
            query: { _id: name },
            update: { $inc: { seq: 1 } },
            new: true
          }
   );

   return ret.seq;
}

insert() 期间使用此 getNextSequence() 函数。

db.users.insert(
   {
     _id: getNextSequence("userid"),
     name: "Sarah C."
   }
)

db.users.insert(
   {
     _id: getNextSequence("userid"),
     name: "Bob D."
   }
)

这样,您可以在同一个计数器集合中维护任意数量的序列。对于 upsert 问题,请查看此链接 Create an auto-increment sequence field 中的 Optimistic Loop block .

第二种方法是使用像 mongodb-autoincrement 这样的 mongoose 中间件。 .

希望对您有所帮助。

关于node.js - MongoDB:处理自动递增的模型 id 而不是 Mongo 的 native ObjectID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33443905/

相关文章:

node.js - 如何从 socket.io 实例内的 koa-session 获取 session 信息?

javascript - 未处理的PromiseRejection警告: undefined in Mongoose

javascript - 如何在 ejs 中显示数据库中的分层数据

node.js - 在passport.js中,中间件方法 "local-signup"具有唯一的 key 电子邮件和密码。可以改也可以不改

javascript - Node : How to read file?

javascript - 如何使用选择器使用 Playwright 查找框架(iframe)

node.js - 在 Google Cloud Function 中按路径需要 key 文件

mongodb - Mongoose findOneAndUpdate 如何返回最后推送的元素

javascript - 未处理的 promise 拒绝警告。使用 npm run test 运行时的警告

ruby-on-rails - rails : Store JSON in MongoDB