在MongoDB中如何实现自增的主键ID?

10

就像在MYSQL中一样,我想要一个自增的ID。

7个回答

21

您需要使用MongoDB的findAndModify命令。通过它,您可以原子地选择并增加一个字段

db.seq.findAndModify({
  query: {"_id": "users"},
  update: {$inc: {"seq":1}},
  new: true
});

这将为users集合的计数器加一,然后您可以在插入文档之前将其添加到文档中。由于它是原子操作,您不必担心竞争条件导致冲突的ID。

这并不像MySQL的auto_increment标志那样无缝,但通常您还可以在Mongo驱动程序中指定自己的ID工厂,因此您可以实现一个使用findAndModify来透明地增加和返回ID的工厂,从而获得更类似于MySQL的体验。

这种方法的缺点是,由于每次插入都依赖于对序列集合的写锁定,如果您进行大量写操作,可能很快就会出现瓶颈。如果您只想保证集合中的文档按插入顺序排序,请查看Capped Collections


13

MongoDB旨在实现水平扩展。在这种情况下,自动递增会导致id碰撞。这就是为什么id更像是guid/uuid的原因。


3

MongoDB提供了两种自动递增_id (或自定义键) 的方式:

计数器集合


在这种方法中,我们需要创建一个集合来存储最大键的数量,并且每次调用该函数时将其递增1。

1. 存储函数

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

   return ret.seq;
}

2. 插入文档

db.users.insert({
  _id: getNextSequence("USER"),
  name: "Nishchit."
})

乐观循环


在这种模式中,乐观循环会计算增加的_id值,并尝试插入一个具有计算出的_id值的文档。如果插入成功,则循环结束。否则,循环将遍历可能的_id值,直到插入成功。

1. 存储函数

function insertDocument(doc, targetCollection) {

    while (1) {

        var cursor = targetCollection.find( {}, { _id: 1 } ).sort( { _id: -1 } ).limit(1);

        var seq = cursor.hasNext() ? cursor.next()._id + 1 : 1;

        doc._id = seq;

        var results = targetCollection.insert(doc);

        if( results.hasWriteError() ) {
            if( results.writeError.code == 11000 /* dup key */ )
                continue;
            else
                print( "unexpected error inserting data: " + tojson( results ) );
        }

        break;
    }
}

2. 插入文档

var myCollection = db.USERS;

insertDocument(
   {
     name: "Nishchit Dhanani"
   },
   myCollection
);

来自 MongoDB 官方文档 的指南


1

如果你怀疑你的数据可能跨越多个服务器(也称为分片),那么请遵循Dennis的建议并使用本地的ObjectId。

如果你更喜欢int/long id(在URL上看起来更好),那么你可以从Chris建议的一个简单的生成器实现开始。当/如果性能/锁定成为问题时,你可以升级你的生成器以实现Hi/Lo算法。这将大大减轻对'seq'集合的压力,并实际上消除这个问题。(客户端生成器使用一个'pool',只有在没有更多的空闲id时才联系数据库)


0

虽然不支持自动递增,但您可以轻松实现自己的小类以发出递增值。

我自己需要这个功能,所以我用php编写了一个小类。我在我的博客上写了一篇文章,请点击这里查看


0

0

我正在使用这个 - mongoose-auto-increment

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    autoIncrement = require('mongoose-auto-increment');

var connection = mongoose.createConnection("mongodb://localhost/myDatabase");

autoIncrement.initialize(connection);

var bookSchema = new Schema({
    author: { type: Schema.Types.ObjectId, ref: 'Author' },
    title: String,
    genre: String,
    publishDate: Date
});

bookSchema.plugin(autoIncrement.plugin, 'Book');
var Book = connection.model('Book', bookSchema);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接