- MongoDB CRUD Operations >
- MongoDB CRUD Tutorials >
- Create an Auto-Incrementing Sequence Field
Create an Auto-Incrementing Sequence Field¶
On this page
Synopsis¶
MongoDB reserves the _id field in the top level of all documents
as a primary key. _id must be unique, and always has an index with
a unique constraint. However, except for
the unique constraint you can use any value for the _id field in
your collections. This tutorial describes two methods for creating an
incrementing sequence number for the _id field using the
following:
Warning
Generally in MongoDB, you would not use an auto-increment pattern
for the _id field, or any field, because it does not scale for
databases with large numbers of documents. Typically the default
value ObjectId is more ideal for the _id.
A Counters Collection¶
Use a separate counters collection to track the last number sequence
used. The _id field contains the sequence name and the seq field
contains the last value of the sequence.
Insert into the
counterscollection, the initial value for theuserid:Create a
getNextSequencefunction that accepts anameof the sequence. The function uses thefindAndModify()method to atomically increment theseqvalue and return this new value:Use this
getNextSequence()function duringinsert().You can verify the results with
find():The
_idfields contain incrementing sequence values:
Note
When findAndModify() includes the upsert:
true option and the query field(s) is not uniquely indexed, the
method could insert a document multiple times in certain
circumstances. For instance, if multiple clients each invoke the
method with the same query condition and these methods complete the
find phase before any of methods perform the modify phase, these
methods could insert the same document.
In the counters collection example, the query field is the
_id field, which always has a unique index. Consider that the
findAndModify() includes the upsert:
true option, as in the following modified example:
If multiple clients were to invoke the getNextSequence() method
with the same name parameter, then the methods would observe one
of the following behaviors:
- Exactly one
findAndModify()would successfully insert a new document. - Zero or more
findAndModify()methods would update the newly inserted document. - Zero or more
findAndModify()methods would fail when they attempted to insert a duplicate.
If the method fails due to a unique index constraint violation, retry the method. Absent a delete of the document, the retry should not fail.
Optimistic Loop¶
In this pattern, an Optimistic Loop calculates the incremented
_id value and attempts to insert a document with the calculated
_id value. If the insert is successful, the loop ends. Otherwise,
the loop will iterate through possible _id values until the insert
is successful.
Create a function named
insertDocumentthat performs the “insert if not present” loop. The function wraps theinsert()method and takes adocand atargetCollectionarguments.The
while (1)loop performs the following actions:- Queries the
targetCollectionfor the document with the maximum_idvalue. - Determines the next sequence value for
_idby:- adding
1to the returned_idvalue if the returned cursor points to a document. - otherwise: it sets the next sequence value to
1if the returned cursor points to no document.
- adding
- For the
docto insert, set its_idfield to the calculated sequence valueseq. - Insert the
docinto thetargetCollection. - If the insert operation errors with duplicate key, repeat the loop. Otherwise, if the insert operation encounters some other error or if the operation succeeds, break out of the loop.
- Queries the
Use the
insertDocument()function to perform an insert:You can verify the results with
find():The
_idfields contain incrementing sequence values:
The while loop may iterate many times in collections with larger
insert volumes.