Подтвердить что ты не робот

Автоматически удалять ссылки на объекты при удалении в MongoDB

Предположим, что у меня есть такая схема:

var Person = new Schema({
    name: String
});

var Assignment = new Schema({
    name: String,
    person: ObjectID
});

Если я удалю человека, все равно могут остаться потерянные задания, оставив ссылку на человека, которого не существует, что создает посторонний беспорядок в базе данных.

Есть ли простой способ гарантировать, что когда человек будет удален, все соответствующие ссылки на это лицо также будут удалены?

4b9b3361

Ответ 1

Вы можете добавить свой собственный 'remove' Mongoose middleware в схему Person, чтобы удалить этого человека из всех других документов, которые ссылаются на него. В вашей функции промежуточного программного обеспечения this является удаляемым документом Person.

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

Ответ 2

Если под "простым" вы подразумеваете "встроенный", то нет. MongoDB не является реляционной базой данных. Вам необходимо реализовать свой собственный механизм очистки.

Ответ 3

Метод remove() устарел.

Таким образом, использование 'remove' в вашем промежуточном программном обеспечении Mongoose, вероятно, больше не является лучшей практикой

Mongoose создал обновления для предоставления хуков для deleteMany() и deleteOne(). Вы можете вместо этого.

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

Ответ 4

вы можете использовать мягкое удаление. Не удаляйте личность из Person Collection вместо использования isDelete boolean flag в true.

Ответ 5

В случае, если кто-то ищет pre-hook, но для deleteOne и deleteMany это решение, которое работает для меня:

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

Вызов функции deleteOne где-то в сервисе:

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