0

In the following link from mongoDB documentation: https://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

there is an explanation on how to build a "safe" insert with auto-incremental _id. My questions are:

  1. Where should i define the function at?
  2. How can i call it later on?

I couldn't quit understand if the function is stored as a JS function is a JS file? or is it stored in the DB? or something else.

Thanks.

Here is the actual function as it is brought in the link above:

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;
}
}
Dmytro Shevchenko
  • 33,431
  • 6
  • 51
  • 67
TBE
  • 1,002
  • 1
  • 11
  • 32
  • Actually that is just the ["optimistic loop"](https://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/#auto-increment-optimistic-loop) example implentation. None of the code is "tied" to a JavaScript implementation. The core parts you need to be reading there are about the [`.findAndModify()`](https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/) method and how it is generally being implemented in examples there, being that a value is incremented and then returned for use as the "auto incrementing key". – Blakes Seven Nov 11 '15 at 11:24
  • The core driver methods ( and the example of implementation ) is available to all languages. So it's just a principle. Update and return a value stored in another collection by incrementing it's current value, then use that value returned as your "incremented key". – Blakes Seven Nov 11 '15 at 11:27
  • Can you please explain how can i use the optimistic loop implementation in my db? What are the steps? I mean, if i want each inserted document in a certain/all collections to have an auto incremental _id but i need it to be safe as well. – TBE Nov 11 '15 at 11:31
  • I don't think you are grasping that this is not a concept in itself, but used in conjunction of the basic "incrementing" principle of data in another collection as is generally described there. Also "your implementation" requires a specification of which language you are actually implementing in. Which is notably missing from your question. – Blakes Seven Nov 11 '15 at 11:36
  • Sorry for that, I'm using Nodejs as a server that communicated with mongoDB using mongoose. I think the there is no escape of using db.system.js right? – TBE Nov 11 '15 at 12:09
  • 1
    @TomerBenEzra please refer to this answer for an example: http://stackoverflow.com/a/30164636/236660 – Dmytro Shevchenko Nov 11 '15 at 12:11
  • 1
    Also, you can use this mongoose module: https://www.npmjs.com/package/mongoose-auto-increment – Dmytro Shevchenko Nov 11 '15 at 12:11
  • 1
    Thank you @Dmytro Shevchenko you answer is what i was looking for! Is it considered thread safe or any other kind data integrity solution? I'm new to node.js and i know that my question might be not relevant. – TBE Nov 12 '15 at 09:16

1 Answers1

1

Implementation approach

Here's an example of how to implement an auto-increment field with mongoose:

var CounterSchema = Schema({
    _id: {type: String, required: true},
    seq: { type: Number, default: 0 }
});
var counter = mongoose.model('counter', CounterSchema);

var entitySchema = mongoose.Schema({
    testvalue: {type: String}
});

entitySchema.pre('save', function(next) {
    var doc = this;
    counter.findByIdAndUpdate({_id: 'entityId'}, {$inc: { seq: 1} }, function(error, counter)   {
        if(error)
            return next(error);
        doc.testvalue = counter.seq;
        next();
    });
});

Source: https://stackoverflow.com/a/30164636/236660

Please note that {_id: 'entityId'} should be set differently per collection you're using this code with. So if you're generating an ID for entitySchema, you'll have {_id: 'entityId'}. For userSchema you would use {_id: 'userId'}, etc. You need to do this so that every collection has its own auto-incremented sequence.

The code above is thread safe. The findByIdAndUpdate operation is atomic; its consistency and concurrency are handled by MongoDB.

Existing module

Also, there is a mongoose module created specifically for handling auto-incremented IDs. You may actually be better off using it:

https://www.npmjs.com/package/mongoose-auto-increment

Community
  • 1
  • 1
Dmytro Shevchenko
  • 33,431
  • 6
  • 51
  • 67