Mongoose populate after save

I cannot manually or automatically populate the creator field on a newly saved object ... the only way I can find is to re-query for the objects I already have which I would hate to do.

This is the setup:

var userSchema = new mongoose.Schema({   
  name: String,
});
var User = db.model('User', userSchema);

var bookSchema = new mongoose.Schema({
  _creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
  description: String,
});
var Book = db.model('Book', bookSchema);

This is where I am pulling my hair

var user = new User();
user.save(function(err) {
    var book = new Book({
        _creator: user,
    });
    book.save(function(err){
        console.log(book._creator); // is just an object id
        book._creator = user; // still only attaches the object id due to Mongoose magic
        console.log(book._creator); // Again: is just an object id
        // I really want book._creator to be a user without having to go back to the db ... any suggestions?
    });
});

EDIT: latest mongoose fixed this issue and added populate functionality, see the new accepted answer.


You should be able to use the Model's populate function to do this: http://mongoosejs.com/docs/api.html#model_Model.populate In the save handler for book, instead of:

book._creator = user;

you'd do something like:

Book.populate(book, {path:"_creator"}, function(err, book) { ... });

Probably too late an answer to help you, but I was stuck on this recently, and it might be useful for others.


The solution for me was to use execPopulate, like so

const t = new MyModel(value)
return t.save().then(t => t.populate('my-path').execPopulate())

In case that anyone is still looking for this.

Mongoose 3.6 has introduced a lot of cool features to populate:

book.populate('_creator', function(err) {
 console.log(book._creator);
});

or:

Book.populate(book, '_creator', function(err) {
 console.log(book._creator);
});

see more at: https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population

But this way you would still query for the user again.

A little trick to accomplish it without extra queries would be:

book = book.toObject();
book._creator = user;

The solution which returns a promise (no callbacks):

Use Document#populate

book.populate('creator').execPopulate();

// summary
doc.populate(options);               // not executed
doc.populate(options).execPopulate() // executed, returns promise

Possible Implementation

var populatedDoc = doc.populate(options).execPopulate();
populatedDoc.then(doc => {
   ... 
});

Read about document population here.