Express pre remove 触发另一个 pre remove on remove
Posted
技术标签:
【中文标题】Express pre remove 触发另一个 pre remove on remove【英文标题】:Express pre remove triggers another pre remove on remove 【发布时间】:2021-08-03 06:16:05 【问题描述】:假设我有 4 个这样的模型:
┌────────────┐ ┌────────────┐
│ User │ │ Goal │
├────────────┤ 1 ├────────────┤ 1
│ _id │◄──┐ │ _id │◄──┐
└────────────┘ └──┤ ref_user │ │
1..*└────────────┘ │
│
┌───────────┐ ┌───────────────┐ │
│ Date │ │ Data │ │
├───────────┤ 1 ├───────────────┤ │
│ _id: date │◄─┐ │ _id │ │
└───────────┘ └──┤ ref_date │ │
1 │ ref_goal ├──┘
└───────────────┘ *
我在删除数据时创建了一个pre remove
,它会自动删除关联的日期。
DataSchema.pre('remove', async function (next)
try
await DateModel.findByIdAndRemove(this.ref_date);
console.log("Date removed");
next();
catch (err)
console.log(err);
next(err);
);
我面临的问题是,当我删除一个目标时,我希望删除所有关联的数据(它有效)但我希望 DataModel.remove 触发其pre remove
并删除其日期。
从逻辑的角度来看,当删除目标中pre remove
钩子上的数据时,这也应该触发数据中的pre remove
,因为删除了数据数据。为什么从另一个 pre remove
钩子中删除数据时不会触发它的 pre remove
?
从 Goal 中,我可以检索数据数组,但我不认为循环遍历数组并逐个删除日期是一个好习惯。
有没有办法触发从数据中的预删除,从目标的预删除?或者一种从数据数组中删除所有日期的方法?
ps:在未来,我想要在删除用户时再次做同样的事情(删除其所有目标,即删除所有数据和日期)。
编辑:
按照要求,他是我的目标,预移除钩子
GoalSchema.pre('remove', async function (next)
try
await DataModel.deleteMany( 'ref_goal': this._id );
console.log("Data removed");
next();
catch (err)
console.log(err);
next(err);
);
我尝试了deleteMany
、remove
等,但似乎都没有触发Data
预删除钩子
环境:
"express": "^4.17.1",
"mongoose": "^5.12.2",
【问题讨论】:
你能显示目标pre remove
钩子吗?
@CuongLeNgoc 完成,我更新了我的问题
你使用的是哪个版本的猫鼬和快递?
并且还添加了日期数据和目标的模式/模型定义。为什么不在数据方案中将日期定义为嵌套模型。如图所示? mongoosejs.com/docs/subdocs.html
@Shasak 我是 react-native 的新手,我不知道嵌套模型。但是,如果我想删除一个用户,问题是一样的,我希望删除它的所有目标,以及目标的所有数据。在未来,我的shema会更复杂,我想了解为什么pre remove hook不会触发另一个schema pre remove hook
【参考方案1】:
您当前的代码有两个问题:
您正在 data
架构上注册 remove
挂钩:
DataSchema.pre('remove', ...)
当你是goal
的remove
钩子的回调triggers一个deleteMany
中间件:
await DataModel.deleteMany(...)
因此data
的remove
挂钩未触发。
现在,您提到您尝试了其他功能,例如remove
,这将我们带到了第二期:
您在文档上注册 remove
挂钩(这是默认设置),同时在模型上执行功能。
在docs 上查看此说明:
注意:如果你指定
schema.pre('remove')
,Mongoose会注册这个doc.remove()
默认的中间件。如果你想要你的中间件 要在Query.remove()
上运行,请使用schema.pre('remove', query: true, document: false , fn)
。
相关的也是这个解释:
您可以将选项传递给
Schema.pre()
和Schema.post()
进行切换 Mongoose 是否将您的remove()
钩子称为Document.remove()
或Model.remove()
。注意这里需要同时设置document
和query
传递对象中的属性:
// Only document middleware schema.pre('remove', document: true, query: false , function() console.log('Removing doc!'); ); // Only query middleware. This will get called when you do `Model.remove()` // but not `doc.remove()`. schema.pre('remove', query: true, document: false , function() console.log('Removing!'); );
我认为以下应该可行:
const onRemoveData = async function (next)
try
let removed = [this];
if (this instanceof mongoose.Query)
removed = await this.model.find(this.getQuery());
removed.forEach(function(doc)
await DateModel.findByIdAndRemove(doc.ref_date);
console.log("Date removed");
);
next();
catch (err)
console.log(err);
next(err);
DataSchema.pre(['remove', 'deleteMany'], document: true, query: false, onRemoveData);
DataSchema.pre(['remove', 'deleteMany'], document: false, query: true, onRemoveData);
【讨论】:
谢谢,现在数据预删除已触发,但this
现在是 Query
,我不知道如何在数据挂钩中使用 this.ref_date
在onRemoveData
函数中,this
是一个Query ...
。如何访问this.ref_date
?
你是对的,正如文档所指出的那样:“如果您需要访问将要更新的文档,则需要对该文档执行显式查询。”我编辑了代码以使其正常工作,请尝试一下。
非常感谢!您的更正工作几乎完美,它只删除了一个Date
,我认为是因为this.model.findOne
。我尝试使用this.modal.find
,但它不会删除任何Date
。我阅读了文档,它只谈论this.model.findOne
哦,对了,find
返回一个数组。我又编辑了,请试一试(注意我还附上了[this]
)。以上是关于Express pre remove 触发另一个 pre remove on remove的主要内容,如果未能解决你的问题,请参考以下文章
[leetcode]203. Remove Linked List Elements链表中删除节点
错误:子进程 已安装 pre-removal 脚本 返回了错误号 1