Automatically remove referencing objects on deletion in MongoDB

If by "simple" you mean "built-in", then no. MongoDB is not a relational database after all. You need to implement your own cleaning mechanism.


The remove() method is deprecated.

So using 'remove' in your Mongoose middleware is probably not best practice anymore.

Mongoose has created updates to provide hooks for deleteMany() and deleteOne(). You can those instead.

Person.pre('deleteMany', function(next) {
    var person = this;
    person.model('Assignment').deleteOne({ person: person._id }, next);
});

In case if anyone looking for the pre hook but for deleteOne and deleteMany functions this is a solution that works for me:

const mongoose = require('mongoose');
... 

const PersonSchema = new mongoose.Schema({
  name: {type: String},
  assignments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Assignment'}]
});

mongoose.model('Person', PersonSchema);

.... 

const AssignmentSchema = new mongoose.Schema({
  name: {type: String},
  person: {type: mongoose.Schema.Types.ObjectId, ref: 'Person'}
});

mongoose.model('Assignment', AssignmentSchema)
...

PersonSchema.pre('deleteOne', function (next) {
  const personId = this.getQuery()["_id"];
  mongoose.model("Assignment").deleteMany({'person': personId}, function (err, result) {
    if (err) {
      console.log(`[error] ${err}`);
      next(err);
    } else {
      console.log('success');
      next();
    }
  });
});

Invoking deleteOne function somewhere in service:

try {
  const deleted = await Person.deleteOne({_id: id});
} catch(e) {
  console.error(`[error] ${e}`);
  throw Error('Error occurred while deleting Person');
}

You can add your own 'remove' Mongoose middleware on the Person schema to remove that person from all other documents that reference it. In your middleware function, this is the Person document that's being removed.

Person.pre('remove', function(next) {
    // Remove all the assignment docs that reference the removed person.
    this.model('Assignment').remove({ person: this._id }, next);
});