我有一个user
集合,我有一个删除用户的 API。但是,我在其他集合中使用用户作为参考,例如 inPosts
也有一个 userId 参考visitRequests
。
有没有合适的方法来做到这一点?还是我应该在每个集合中做一个这样的特定查询?
await User.findOneAndDelete({ _id: id });
await visitRequestModel.findOneAndDelete(
{_userId: id},
);
...
我还想例如更改 Posts 集合中的状态而不是删除它。
而且,这可以用聚合方法来完成吗?
解决此问题的一种流行方法是使用 MongoDB 的前/后保存挂钩中的任何一个来进行删除查询。但我推荐的一个更好的解决方案是使用 MongoDB 事务,考虑到要删除的引用数量可能会随着应用程序的增加而增加,并且您希望更新帖子的状态而不是删除。如果您从关系数据库原生的 ACID 角度来看,事务非常有用。为避免不一致,因为在您提出的上述方法或什至使用挂钩时,一个查询可能会在其他查询运行后失败,这对您的应用程序可能非常不利。所以事务解决了这个问题,因此要走的路如下:
const connection = mongoose.connection;
const session = await connection.startSession();
console.log('started new session')
// it is advisable to use a try/catch block here to handle failures and rollback
try {
await session.startTransaction();
console.log('transaction started'); //just some logging;
await User.findOneAndDelete({ _id: id }, { session });
await visitRequestModel.findOneAndDelete({ _id: id }, { session });
// now to update your post's status
await Posts.updateOne({ _id: id }, { status: 'newStatus' }, { session });
await session.commitTransaction();
console.log('transaction(delete operation) successful');
} catch (error) {
console.log('transaction failed');
throw new Error(err);
await session.abortTransaction();
}
await connection.endSession();
console.log('session ended')
这样,abortTransaction()
如果过程中发生错误或查询失败,您可以保证您的数据一致性,并且一切都回滚到以前的方式。您还可以添加甚至与会话无关的其他查询,只需记住{ session }
作为参数传递的查询是与正在运行的事务关联的查询。
注意:如果您使用的是自托管 MongoDB 实例(可能是您的本地安装),您可能必须配置 MongoDB 副本集/分片集群,因为独立 MongoDB 安装不支持事务。但是,如果您使用的是 Atlas,那么无需任何配置即可。
希望这可以帮助...
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句