在MongoDB中删除时自动删除引用对象

时间:2012-08-10 14:50:26

标签: node.js mongodb mongoose

假设我有这样的架构:

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

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

如果我删除一个人,仍然会有一些孤立的作业,引用一个不存在的人,这会在数据库中造成无关紧要的混乱。

是否有一种简单的方法可以确保在删除某个人时,还会删除对该人的所有相应引用?

6 个答案:

答案 0 :(得分:30)

您可以在'remove'架构上添加自己的Person Mongoose middleware,以便将该人从引用它的所有其他文档中删除。在您的中间件功能中,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);
});

答案 1 :(得分:10)

如果“简单”是指“内置”,那么没有。毕竟,MongoDB不是关系数据库。您需要实施自己的清洁机制。

答案 2 :(得分:2)

不推荐使用remove()方法。

因此,在您的Mongoose中间件中使用“删除”可能不再是最佳做法。

Mongoose has created updates to provide hooks for deleteMany() and deleteOne()。 您可以改为那些。

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

答案 3 :(得分:1)

你可以使用软删除。不要从Person Collection中删除person,而是使用isDelete boolean flag为true。

答案 4 :(得分:0)

如果有人要寻找除deleteOnedeleteMany函数之外的前置钩子,这是对我有用的解决方案:

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

答案 5 :(得分:0)

即使删除参考人文档,您也可以保留文档原样。 Mongodb会清除指向不存在文档的引用,这不会在删除引用文档后立即发生。相反,当您对文档执行操作时,例如,更新。而且,即使您在清除引用之前查询数据库,返回的也是空值,而不是空值。

第二个选项是使用$unset运算符,如下所示。

{ $unset: { person: "<person id>"} }

请注意使用人员ID来表示查询中引用的值。