Автоматически удалять ссылки на объекты при удалении в MongoDB
Предположим, что у меня есть такая схема:
var Person = new Schema({
name: String
});
var Assignment = new Schema({
name: String,
person: ObjectID
});
Если я удалю человека, все равно могут остаться потерянные задания, оставив ссылку на человека, которого не существует, что создает посторонний беспорядок в базе данных.
Есть ли простой способ гарантировать, что когда человек будет удален, все соответствующие ссылки на это лицо также будут удалены?
Ответы
Ответ 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');
}