About the Author

Chris Shiflett

Hi, I'm Chris, a web developer and a founding member of Analog. I live and work in Brooklyn, NY.


All Posts for Blog

Auto Increment with MongoDB

We are currently working on an app that uses a number of technologies, including PHP, Python, and MongoDB. Recently, a need arose to use sequential identifiers for users, similar to an auto_increment column in MySQL.

If you've used MongoDB, you might be familiar with the default behavior of using a UUID as the primary key. This is convenient, especially if you partition your database across servers, because you don't have to coordinate the primary key in any way. If you use sequential identifiers (as I demonstrate in this post), you can use multiple servers and interleave identifiers by advancing each server's sequence by the total number of servers. (For example, with two servers, advance each sequence by two, so one server generates even identifiers, and the other generates odd.)

I'd rather not discuss the advantages and disadvantages of either approach, because it's exactly this debate that makes it very difficult to find any useful information on using sequential identifiers with MongoDB. Instead, I'm just going to explain how I did it, and hope this is helpful to someone. :-)

First, create a sequence collection that you can use to determine the next identifier in the sequence. The following creates a collection called seq that has a single sequence in it (for users), but you can add as many as you need:

db.seq.insert({"_id":"users", "seq":new NumberLong(1)});

If you assign seq to 1 instead of new NumberLong(1), it will be interpreted as a float due to a JavaScript quirk.

Before adding a new user, you need to increment the sequence by one and fetch the next identifier. Fortunately, the findandmodify() command provides an atomic way to do this. Using the MongoDB shell, the command would look something like this:

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

Because I'm using Lithium, I added a method for fetching the next identifier to my User model:

<?php
 
namespace app\models;
 
class User extends \lithium\data\Model {
 
    static public function seq() {
        $seq = static::_connection()->connection->command(
            array('findandmodify' => 'seq',
                  'query' => array('_id' => 'users'),
                  'update' => array('$inc' => array('seq' => 1)),
                  'new' => TRUE
            )
        );
 
        return $seq['value']['seq'];
    }
 
}
 
?>

If you're not using Lithium, you can use the MongoDB class to execute a command().

With this in place, adding a new user is a simple process. I create an array called $data with everything I want to store for a user, and then do the following:

<?php
 
$user = User::create($data);
$user->_id = User::seq();
$success = $user->save();
 
?>

This example should be easy to adapt to any environment. Once you have the next identifier in the sequence, you simply store it as you would any other data.

I hope to blog more about both MongoDB and Lithium. As these technologies are still pretty new to me, please feel free to point out any improvements. I'll update the post accordingly.

Upcoming Events

Brooklyn Beta

21 - 22 Oct 2010

At The Invisible Dog, Brooklyn, New York.

New Comments

Chris Shiflett wrote:

Hi John, How do you avoid race conditions with this? The findandmodify() command is atomic,...

Posted in Auto Increment with MongoDB
John Judy wrote:

How do you avoid race conditions with this? Once you get to a certain traffic volume two or more ...

Posted in Auto Increment with MongoDB
Chris Shiflett wrote:

Hey Ivo, Andrei is best suited to give a full response, since he's the one who researched this...

Posted in Auto Increment with MongoDB
Ivo wrote:

Although you did mention that you werent going to discuss the why, I can't think of a single vali...

Posted in Auto Increment with MongoDB
Stikkyfinger wrote:

Jon Gibbins plays a mean guitar? I'd be interested to know what he plays and what type of guitar ...

Posted in Hello, Analog

Browse Comments


Work and Books

Analog Essential PHP Security HTTP Developer's Handbook