使用Mongoose中的UUID作为ObjectID引用

我正在用Node.js,Express和MongoDB使用mongoose构build一个CRUD风格的REST服务。 该服务将允许已经存在的android应用程序的用户在线上传/同步他们各个数据库的内容。

现有应用程序的数据模型使用UUID(用Java生成)与较短的单调MongoDB样式_id字段冲突。 由于数据模型已经存在,并且被来自许多用户的数据填充,所以我无法将源数据转换为单调的MongoDB样式_id 。 这让我想到了两个选项:1)让Mongo / Mongoose(或者其他一些ODM)可以用完整的UUID代替单调的_id s,或者2)为mongoose模型添加一个uuid字段到_id领域,并打破这种做法的陷阱。 我试图select#1选项,并遇到ObjectID引用的问题。

我最初偶然发现了mongoose-uuid ,但不幸的是,这不能正常工作,因为它在创build新的Mongoose对象时覆盖了我明确设置的_id值。 潜入插件代码,它假定一个对象是新的(通过调用检查Mongoose的.isNew值),从而用新的uuid覆盖_id 。 由于在Mongo中创build新文档时我需要保留原始的uuid,所以这个插件不适合我。

接下来,我发现mongoose的创始人亚伦·赫克曼(Aaron Heckmann)在一个类似的话题上发表了一篇文章 。 这是有帮助的,但是我现在遇到了我不能让我的mongoose模式通过ObjectID相互引用的问题,因为他们在技术上现在使用String`_ids来引用对方。

架构示例:

 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); 

引用模式:

 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); 

当我尝试调用save()从我的应用程序传入的trackPass时:

 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) { ... } 

我得到以下错误:

 { [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' } 

我相信这个错误是有道理的,因为我现在使用比典型的Mongo ObjectID更长的string。 没有ObjectID引用,我不相信我将能够从其他集合populate()引用的对象。 我想我可以简单地不引用我的模式定义中的其他嵌套对象,但是我不喜欢这种方法,因为我觉得我会失去很多使用ODM的好处。 任何其他的想法?

您仍然可以使用除了ObjectID之外的types为_id populate() ,但您需要在引用定义中使用相同的types。

所以你的trackPassSchema将需要改变为:

 var trackPassSchema = new Schema({ _id: { type: String, default: function genUUID() { uuid.v1() }}, vehicle: [ {type: String, required: true, ref: 'Vehicle'} ] }); 

正如Adam在评论中所指出的那样,您可以将您的default值简化为:

 var trackPassSchema = new Schema({ _id: { type: String, default: uuid.v1 }, vehicle: [ {type: String, required: true, ref: 'Vehicle'} ] });