我有一個user集合,我有一個洗掉用戶的 API。但是,我在其他集合中使用用戶作為參考,例如 inPosts也有一個 userId 參考visitRequests。
有沒有合適的方法來做到這一點?還是我應該在每個集合中做一個這樣的特定查詢?
await User.findOneAndDelete({ _id: id });
await visitRequestModel.findOneAndDelete(
{_userId: id},
);
...
我還想例如更改 Posts 集合中的狀態而不是洗掉它。
而且,這可以用聚合方法來完成嗎?
uj5u.com熱心網友回復:
解決此問題的一種流行方法是使用 MongoDB 的前/后保存掛鉤中的任何一個來進行洗掉查詢。但我推薦的一個更好的解決方案是使用 MongoDB 事務,考慮到要洗掉的參考數量可能會隨著應用程式的增加而增加,并且您希望更新帖子的狀態而不是洗掉。如果您從關系資料庫原生的 ACID 角度來看,事務非常有用。為避免不一致,因為在您提出的上述方法甚至使用掛鉤時,一個查詢可能會在其他查詢運行后失敗,這對您的應用程式可能非常不利。所以事務解決了這個問題,因此要走的路如下:
- 在您必須連接到資料庫后獲取您的 Mongodb 連接。
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,那么無需任何配置即可。
- 更多關于副本集的資訊在這里
- 更多關于 ACID 和 MongoDB 事務的資訊在這里
希望這可以幫助...
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/491363.html
