2014-12-12 7 views
11

Sto costruendo un servizio REST in stile CRUD con Node.js, Express e MongoDB utilizzando mangusta. Questo servizio consentirà agli utenti di un'applicazione Android già esistente di caricare/sincronizzare i contenuti dei loro singoli database online.Utilizzo di UUID in mangusta per i riferimenti all'ObjectID

Il modello dati per l'applicazione già esistente utilizza UUID (generati in Java) che si scontrano con i campi di stile _id monotonici di MongoDB più brevi. Poiché il modello di dati esiste già e viene popolato con i dati di molti utenti, non riesco a convertire i dati di origine in stile monotonico MongoDB _id s. Questo mi ha lasciato con 2 opzioni a cui posso pensare: 1) Crea Mongo/Mongoose (o qualche altro ODM) gioca bene con UUID completi invece del monotonico _id s o 2) aggiungi un campo uuid al modello di mangusta in aggiunta al campo _id e combattere le insidie ​​di questo approccio. Sto tentando di scegliere l'opzione n. 1 e l'esecuzione di problemi con i riferimenti a ObjectID.

Originariamente mi sono imbattuto in mongoose-uuid, ma sfortunatamente questo non funziona correttamente per il mio caso d'uso perché sovrascriveva il mio valore esplicitamente impostato _id durante la creazione di nuovi oggetti Mongoose. Immergendosi nel codice del plugin, si presuppone che un oggetto sia nuovo (chiamando il valore di .isNew di Mongoose) e quindi sovrascrive lo _id con un nuovo uuid. Poiché ho bisogno di mantenere l'uuid originale quando creo nuovi documenti in Mongo, questo plugin non funziona per me.

Successivamente, ho trovato un post di Aaron Heckmann, creatore di mangusta, su un argomento simile. Questo è stato utile, tuttavia ora sto riscontrando il problema in cui non riesco a far riferimento ai miei schemi di mangimi in base a ObjectID, dal momento che tecnicamente stanno facendo riferimento l'un l'altro usando String `_id.

schema esempio:

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

Riferimento schema:

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

Quando tento di chiamare save() un trackPass che è stata passata in dalla mia applicazione:

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

ottengo il seguente errore:

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

Credo che questo errore abbia senso poiché ora utilizzo le stringhe che sono più lunghe dei tipici ID oggetto Mongo. Senza avere il riferimento all'ObjectID, non credo che sarò in grado di fare il populate() oggetti di riferimento da altre collezioni. Suppongo che potrei semplicemente non fare riferimento agli altri oggetti nidificati nelle definizioni dello schema, tuttavia non mi piace questo approccio poiché ritengo che perderò molti dei benefici dell'utilizzo dell'ODM. Qualche altro pensiero?

risposta

14

È ancora possibile utilizzare populate() con valori _id di tipi oltre a ObjectID, ma è necessario utilizzare lo stesso tipo nella definizione di riferimento.

Così il vostro trackPassSchema avrebbe bisogno di cambiare per:

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

Come Adam fa notare nei commenti, si potrebbe semplificare il vostro valore default a:

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

Si potrebbe semplificare questo un po ': '_id : {type: String, default: uuid.v1} ' –

+0

@AdamC il tuo suggerimento renderebbe l'uuid generato costante durante la vita di questo oggetto. –

+2

No, va bene. 'default: uuid.v1()' avrebbe quel problema, ma non 'default: uuid.v1'. – JohnnyHK