I have two collections, the first with an array of id’s referencing documents in the second collection.
There is a particular place where I want to create a new DocumentType, then a new Document that references that DocumentType and finally update the original DocumentType to reference the new Document.
A DocumentType can have many Documents but a Document can only have a single DocumentType. The reason why I want to have the reference in both places is to simplify more complex queries later on.
My question is: is there a better way to write it using mongoose than to have these mulitple nested callbacks.
I’ve put together a simple example to demonstrate. There is more data in the real thing and as such I don’t want to have Documents embedded in DocumentTypes or visa versa.
var DocumentTypeSchema = new Schema({
name: String
, desc: String
, documents: [{type: Schema.ObjectId, ref: 'Document'}]
, ...
});
var DocumentSchema = new Schema({
title: String
, doctype: {type: Schema.ObjectId, ref: 'DocumentType'}
, ...
});
var Document = mongoose.model('Document', DocumentSchema);
var DocumentType = mongoose.model('DocumentType', DocumentTypeSchema);
// Begin the nested callbacks
// Create a document type
var type = new DocumentType({...});
// Save document type
type.save(function(err) {
// Create new document
var document = new Document({
doctype: type.id
, ...
});
// Save document
document.save(function(err) {
// Update document type
DocumentType.update({_id: document.doctype}, {'$addToSet': {documents: document.id}}, function(err) {});
});
});
Thanks for your help
I would say that there generally is not a better way for synchronous processing. The
seriesfunction of theasynclibrary mentioned by Jani is a fine way to flatten this, but I think it’s generally a good idea to stick with the callback structure – it makes the scoping very clear and reduces your external dependencies – unless the nesting gets to be absurd or you need async. Your nesting is not absurd, though you might consider async.parallel going forward. If you’re creating two new instances and saving attributes across both, there’s no reason to do the creation synchronously. Instead, something like this:It requires an extra save, and frankly may be silly for a task like this with so little performance overhead, but it illustrates a good approach for async processing and the versatility of the async library.