46

假设我有这样的架构:

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

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

如果我删除一个人,仍然会留下引用不存在的人的孤立分配,这会在数据库中产生无关的混乱。

有没有一种简单的方法可以确保当一个人被删除时,对该人的所有相应引用也将被删除?

4

7 回答 7

45

您可以在架构上添加自己的'remove'Mongoose中间件Person,以将该人从引用它的所有其他文档中删除。在您的中间件函数中,thisPerson要删除的文档。

Person.pre('remove', function(next) {
    // Remove all the assignment docs that reference the removed person.
    this.model('Assignment').remove({ person: this._id }, next);
});
于 2012-08-10T15:48:31.150 回答
16

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

于 2012-08-10T15:05:01.733 回答
8

remove()方法已弃用。

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

Mongoose 已经创建了更新来为deleteMany()deleteOne()提供钩子。你可以用那些代替。

Person.pre('deleteMany', function(next) {
    var person = this;
    person.model('Assignment').deleteOne({ person: person._id }, next);
});
于 2019-03-25T12:57:24.117 回答
5

如果有人在寻找 pre hook 但 for deleteOneand deleteManyfunctions 这对我来说是一个解决方案:

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');
}
于 2019-06-06T20:22:13.703 回答
2

您可以使用软删除。不要从 Person Collection 中删除人员,而是使用 isDelete 布尔标志设置为 true。

于 2017-09-21T06:14:31.507 回答
0

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

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

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

注意在查询中使用 person id 来表示引用的值。

于 2020-08-21T19:07:30.853 回答
0

您可以像这样简单地调用需要删除的模型并删除该文档:

PS:这个答案并不特定于问题模式。

const Profiles = require('./profile');

userModal.pre('deleteOne', function (next) {
  const userId = this.getQuery()['_id'];
  try {
    Profiles.deleteOne({ user: userId }, next);
  } catch (err) {
    next(err);
  }
});

// 在用户删除路由中

exports.deleteParticularUser = async (req, res, next) => {
  try {
    await User.deleteOne({
      _id: req.params.id,
    });

    return res.status(200).json('user deleted');
  } catch (error) {
    console.log(`error`, error);
    return next(error);
  }
};
于 2021-09-16T11:23:13.737 回答