Create unique autoincrement field with mongoose

39,523

Solution 1

const ModelIncrementSchema = new Schema({
    model: { type: String, required: true, index: { unique: true } },
    idx: { type: Number, default: 0 }
});

ModelIncrementSchema.statics.getNextId = async function(modelName, callback) {
    let incr = await this.findOne({ model: modelName });

    if (!incr) incr = await new this({ model: modelName }).save();
    incr.idx++;
    incr.save();
    return incr.idx;
};


const PageSchema = new Schema({
    id: { type: Number ,  default: 0},
    title: { type: String },
    description: { type: String }
});


PageSchema.pre('save', async function(next) {
    if (this.isNew) {
        const id = await ModelIncrement.getNextId('Page');
        this.id = id; // Incremented
        next();
    } else {
        next();
    }
});

Solution 2

Yes, here's the "skinny" on that feature.

You need to have that collection in your mongo database. It acts as concurrent key allocation single record of truth if you want. Mongo's example shows you how to perform an "atomic" operation to get the next key and ensure that even there are concurrent requests you will be guaranteed to have the unique key returned without collisions.

But, mongodb doesn't implement that mechanism natively, they show you how to do it. They only provide for the _id to be used as unique document key. I hope this clarifies your approach.

To expand on the idea, go ahead and add that mongo suggested implementation to your defined Mongoose model and as you already guessed, use it in Pre-save or better yet pre-init event to ensure you always generate an id if you work with a collection server side before you save it to mongo.

Share:
39,523

Related videos on Youtube

Glen Swift
Author by

Glen Swift

I dare you, i double dare you, say what again

Updated on January 18, 2020

Comments

  • Glen Swift
    Glen Swift over 4 years

    Given a Schema:

    var EventSchema = new Schema({
        id: {
            // ...
        },
        name: {
            type: String
        },
    });
    

    I want to make id unique and autoincrement. I try to realize mongodb implementation but have problems of understanding how to do it right in mongoose.

    My question is: what is the right way to implement autoincrement field in mongoose without using any plugins and so on?

    • Glen Swift
      Glen Swift about 10 years
      I really spend much time and try to do it myself. Sorry for such a dummy question
    • Glen Swift
      Glen Swift about 10 years
      I tried to increment id pre save. But how must I work with counters collection? Must i have schema for it? This is the questions i ca not figure out
  • naor.z
    naor.z over 4 years
    Actually this is a bad approach and should be ignored, the type of operation he requests needs to be atomic. In case of concurrent requests, you can easily get the same id twice.
  • Prathamesh More
    Prathamesh More over 4 years
    Yeah! This is not a solution for production-ready apps.
  • Aloy A Sen
    Aloy A Sen about 4 years
    the operation you suggested may go unattended if server stress is high ... the operation is a macromolecule and not atomic
  • Dan Dascalescu
    Dan Dascalescu about 4 years
    What's the point of using that instead of Mongo's native ObjectId? That package also generates a long identifier, and the OP presumably wants something short and readable, or else they'd use ObjectId, which is also always-incrementing, just not by 1.
  • Dan Dascalescu
    Dan Dascalescu about 4 years
    Code-only answers can be improved by explaining how the code works!