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

时间:2010-12-05 02:10:52

标签: mysql mongodb database

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

7 个答案:

答案 0 :(得分:18)

您需要使用MongoDB的findAndModify命令。有了它,你可以atomically select and increment a field

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

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

它不像MySQL的auto_increment标志那样无缝,但您通常也可以选择在Mongo驱动程序中指定自己的ID工厂,这样就可以实现一个使用findAndModify来透明地递增和返回ID的工厂,导致更像MySQL的体验。

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

答案 1 :(得分:13)

MongoDB旨在水平扩展。在这种情况下,自动增量会导致id冲突。这就是为什么id看起来更像guid / uuid。

答案 2 :(得分:2)

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

Counter Collection

这里我们需要创建一个存储最大键数的集合,并在每次调用此函数时递增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。 INSERT DOC

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。 INSERT DOC

var myCollection = db.USERS;

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

来自 MongoDB的官方文档。

答案 3 :(得分:1)

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

如果您更喜欢int / long id(在url上看起来更好),那么您可以使用Chris建议的findAndModify开始使用生成器的天真实现。 当/如果性能/锁定开始成为问题,您可以升级您的发电机以实现Hi / Lo算法。这将减少'seq'系列的压力。并实际上消除了这个问题。 (客户端生成器使用'池',只有在没有更多空闲ID时才与DB联系)

答案 4 :(得分:0)

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

我自己需要这个功能,所以我在php中编写了一个小类。我在我的博客上写了这篇文章,take a look here

答案 5 :(得分:0)

@TIMEX:检查以下链接是否可以帮助您,如果您正在寻找序列号而不是ID(coz ID由mongo保留)

http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/#auto-increment-counters-collection

@Dennis Burton 如果用户自动增加它不会导致碰撞?我觉得,因此mongo db使用自己的_Id,因此它可以避免碰撞,但如果用户希望有一个列作为运行序列,他们可以自由地使用它

答案 6 :(得分: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);