Generating unique IDs

In both our movie and actor schemas, we used a plugin called generateId().

While MongoDB automatically generates ObjectID for each document using the _id field, we want to generate our own IDs that are more human readable and hence friendlier. We also would like to give the user the opportunity to select their own id of choice.

However, being able to choose an id can cause conflicts. If you were to choose an id that already exists, your POST request would be rejected. We should autogenerate an ID if the user does not pass one explicitly.

Without this plugin, if either an actor or a movie is created without an explicit ID passed along by the user, the server would complain since the ID is required.

We can create middleware for Mongoose that assigns an id before we persist the object as follows:

// /src/models/plugins/generateId.js 
module.exports = function() {

return function generateId(schema){ 
  schema.pre('validate',function(next, done) {
    var instance = this; 
    var model = instance.model(instance.constructor.modelName); 

    if( instance.id == null ) {
     model.findOne().sort("-id").exec(function(err,maxInstance) {
       if (err){
         return done(err);
       } else {
         var maxId = maxInstance.id || 0; 
         instance.id = maxId+1;
         done();
       }
    })
   } else { 
     done();
    }
  })
 }
};

There are a few important notes about this code.

See what we did to get the var model? This makes the plugin generic so that it can be applied to multiple Mongoose schemas.

Notice that there are two callbacks available: next and done. The next variable passes the code to the next pre-validation middleware. That's something you would usually put at the bottom of the function right after you make your asynchronous call. This is generally a good thing since one of the advantages of asynchronous calls is that you can have many things running at the same time.

However, in this case, we cannot call the next variable because it would conflict with our model definition of id required. Thus, we just stick to using the done variable when the logic is complete.

Another concern arises due to the fact that MongoDB doesn't support transactions, which means you may have to account for this function failing in some edge cases. For example, if two calls to POST /actor happen at the same time, they will both have their IDs auto incremented to the same value.

Now that we have the code for our generateId() plugin, we require it in our actor and movie schema as follows:

var generateId = require('./plugins/generateId'),
actorSchema.plugin(generateId());
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.37.20