Chan Chen Coding...

Make Auto Incrementing Field in MongoDB

Side counter method
One can keep a counter of the current _id in a side document, in a collection dedicated to counters.
Then use FindAndModify to atomically obtain an id and increment the counter.

> db.counters.insert({_id: "userId", c: 0});

> var o = db.counters.findAndModify(
...        {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 0 }
> db.mycollection.insert({_id:o.c, stuff:"abc"});

> o = db.counters.findAndModify(
...        {query: {_id: "userId"}, update: {$inc: {c: 1}}});
{ "_id" : "userId", "c" : 1 }
> db.mycollection.insert({_id:o.c, stuff:"another one"});
Once you obtain the next id in the client, you can use it and be sure no other client has it.

Optimistic loop method
One can do it with an optimistic concurrency "insert if not present" loop. The following example, in Mongo shell Javascript syntax, demonstrates.

// insert incrementing _id values into a collection
function insertObject(o) {
    x = db.myCollection;
    while( 1 ) {
        // determine next _id value to try
        var c = x.find({},{_id:1}).sort({_id:-1}).limit(1);
        var i = c.hasNext() ? c.next()._id + 1 : 1;
        o._id = i;
        x.insert(o);
        var err = db.getLastErrorObj();
        if( err && err.code ) {
            if( err.code == 11000 /* dup key */ )
                continue;
            else
                print("unexpected error inserting data: " + tojson(err));
        }
        break;
    }
}
The above should work well unless there is an extremely high concurrent insert rate on the collection. In that case, there would be a lot of looping potentially.


-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;

posted on 2012-04-14 01:11 Chan Chen 阅读(330) 评论(0)  编辑  收藏 所属分类: DB


只有注册用户登录后才能发表评论。


网站导航: