Automatically Populate Subdocuments After Saving

Viewed 5440

I would like to always populate subdocuments after saving a particular Model automatically. What I would really like is something like below:

MyModel.post('save', function(doc, next) {
    doc.populate('path').then(next);
});

However, the above won't work because

post middleware do not directly receive flow control, e.g. no next or done callbacks are passed to it. post hooks are a way to register traditional event listeners for these methods.

Of course, there are "Asynchronous Post Hooks", but they still do not receive control flow so there is no guarantee the subdocuments will be populated when I need it.

Why not just use an embedded document? For this case, the subdocuments are the same as the parent document (e.g. I'm using something like the Composite pattern), which would cause a circular dependency that I'm not certain how to resolve (or if I can even resolve it). For other instances, I might want to be able to access the subdocuments without going through the parent document.

Another approach I considered is something like:

const nativeSave = /* ? */;

MyModel.methods.save = function save() {
    return nativeSave.call(this).then(function(savedDoc) {
        return savedDoc.populate('path');
    });
};

However, there are two problems with this. First of all, it seems a like a round-about solution. If there is a more native approach that doesn't go against mongoose's implementation, I would prefer that. Secondly, I don't know what I would set nativeSave to (as apparent by the /* ? */).

So, what are some suggestions for getting this behavior? If my second solution would be the best with the current version of mongoose, what should I set nativeSave to? I've already considered embedded documents, so please don't suggest using them unless you are providing a suggestion about resolving the circular dependency. Even then, I would like a solution for the other use-case I mentioned.

As explained in my comment, this is not the same as manually populating a subdocument after saving as other posts have asked. I want this to happen automatically to avoid leaking my implementation details (e.g. using ObjectIds instead of real documents).

4 Answers

This will help

http://frontendcollisionblog.com/mongodb/2016/01/24/mongoose-populate.html

 var bandSchema = new mongoose.Schema({
  name: String,
  lead: { type: mongoose.Schema.Types.ObjectId, ref: 'person' }
});

var autoPopulateLead = function(next) {
  this.populate('lead');
  next();
};

bandSchema.
  pre('findOne', autoPopulateLead).
  pre('find', autoPopulateLead);

var Band = mongoose.model('band', bandSchema);
// extract only key of body
// const updates = Object.keys(req.body);
let model = Model.findById({_id}
// map automatically attributes
_.extend(congregation, req.body); // using lodash

// OR
// updates.forEach(update => {
//   model[update] = req.body[update];
// });

await model.save().then(model => // without curly braces
      model
        .populate('a')
        .populate('b')
        .populate('c')
        .populate('d')
        .execPopulate(),
    );

res.status(201).send(model);
Related