title: Using UUIDs in mongoose for ObjectID references
body: <p>I'm building a CRUD-style REST service with Node.js, Express and MongoDB using mongoose.  This service is going to allow users of an already existing android application to upload/sync the contents of their individual databases online.</p>
  
  <p>The data model for the already-existing application uses UUIDs (generated in Java) which clashes with the shorter, monotonic MongoDB style <code>_id</code> fields.  Because the data model already exists and is  populated with data from many users, I cannot convert the source data over to monotonic MongoDB-style <code>_id</code>s.  This has left me with 2 options that I can think of: either 1) Make Mongo/Mongoose (or some other ODM) play nicely with full UUIDs instead of the monotonic <code>_id</code>s or 2) add a uuid field to the mongoose model in addition to the <code>_id</code> field and fight the pitfalls of this approach.  I'm attempting to choose option #1 and running into issues with ObjectID references.</p>
  
  <p>I originally stumbled upon <a href="https://www.npmjs.com/package/mongoose-uuid">mongoose-uuid</a>, but unfortunately this isn't working for my use-case properly because it was overwriting my explicitly-set <code>_id</code> value when creating new Mongoose objects.  Diving into the plugin code, it assumes that an object is new (by calling checking Mongoose's <code>.isNew</code> value) and thus overwrites the <code>_id</code> with a new uuid.  Since I need to retain the original uuid when creating new documents in Mongo, this plugin isn't working for me.</p>
  
  <p>Next, I found a <a href="https://github.com/LearnBoost/mongoose/issues/1026">post</a> by Aaron Heckmann, creator of mongoose, on a similar topic.  This has been helpful, however I am now encountering the problem where I cannot have my mongoose schemas reference each other by ObjectID, since they technically they are now referencing each other using String `_ids.</p>
  
  <p>Schema example:</p>
  
  <pre class="lang-js prettyprint-override"><code>var mongoose = require('mongoose');
  var uuid = require('node-uuid');
  
  var Schema = mongoose.Schema;
  
  var trackPassSchema = new Schema({
      _id: { type: String, default: function genUUID() {
          uuid.v1()
      }},
      //Omitting other fields in snippet for simplicity
      vehicle: [
          {type: Schema.Types.ObjectId, required: true, ref: 'Vehicle'}
      ]
  });
  
  module.exports = mongoose.model('TrackPass', trackPassSchema);
  </code></pre>
  
  <p>Referencing schema:</p>
  
  <pre class="lang-js prettyprint-override"><code>var mongoose = require('mongoose');
  var uuid = require('node-uuid');
  
  var Schema = mongoose.Schema;
  
  var vehicleSchema = new Schema({
      _id: { type: String, default: function genUUID() {
          uuid.v1()
      }},
      //Omitting other fields in snippet for simplicity
      description: {type: String},
      year: {type: Number}
  });
  
  module.exports = mongoose.model('Vehicle', vehicleSchema);
  </code></pre>
  
  <p>When I attempt to call <code>save()</code> a trackPass that has been passed in from my application:</p>
  
  <pre class="lang-js prettyprint-override"><code>var trackPass = new TrackPass(req.body);
  
  //Force the ID to match what was put into the request
  trackPass._id = req.params.id;
  trackPass.save(function (err) { ... }
  </code></pre>
  
  <p>I get the following error:</p>
  
  <pre><code>{ [CastError: Cast to ObjectId failed for value "b205ac4d-fd96-4b1e-892a-d4fab818ea2a" at path "vehicle"]
    message: 'Cast to ObjectId failed for value "b205ac4d-fd96-4b1e-892a-d4fab818ea2a" at path "vehicle"',
    name: 'CastError',
    type: 'ObjectId',
    value: ["b205ac4d-fd96-4b1e-892a-d4fab818ea2a"],
    path: 'vehicle' }
  </code></pre>
  
  <p>I believe this error makes sense as I'm now using Strings which are longer than typical Mongo ObjectIDs.  Without having the ObjectID reference, I don't believe I will be able to <code>populate()</code> referenced objects from other collections.  I suppose I could simply not reference the other nested objects in my schema definitions, however I don't like this approach as I feel I will be losing a lot of the benefit of utilizing the ODM.  Any other thoughts? </p>