有一個使用者課程預約的項目,因為後端有node來做,所以mongodb是個很好的選擇,可是因為課程預約系統存在使用者預約成功後,或取消預約後,會有課程預約資訊的事務操作,我對mongo的了解是她不適合用在事務場景裡,我對資料庫的設計不是很了解,想請課程預約這樣的專案適合用mongodb嗎?
给我你的怀抱2017-05-02 09:27:40
MongoDB不適合用於強事務的場景,但很多場景需要的往往不是真的強事務,而可以用最終一致性取而代之。很多強事務也可以透過資料模型設定的技巧轉變成MongoDB的文檔原子性從而避免強事務。你需要更清楚地描述你所說的事務到底是怎樣的場景,才好判斷是不是可以避免。
對於我自己理解的課程預約場景來說,並不是一個很強的非MongoDB不可的場景,但也不是一個非RDBMS不可的場景。所以要說是不是適合用MongoDB,還是建議具體情況具體分析。
=== 2017.4.9 更新 ===
根據評論裡的更新,做以下補充說明:
限制人數這個需求來說可以用MongoDB的文檔原子性來解決。我理解的報名這個場景來講,無非是記錄誰報了哪個課程,一共多少人報了,以及控制不要超報名限額。那麼課程的資料結構可以設計成類似這樣:
{
_id: ObjectId("58e9f6cd58d2c10959c8619a"),
title: "MongoDB入门教程",
intro: "演示用",
createdAt: ISODate("2017-04-09T17:00:00Z"),
createdBy: {
userId: 12345,
name: "MongoDB中文社区"
// 其他必要的信息
},
allowedAttendeeQty: 50, // 允许参与的人数
reservations: {
qty: 0, // 已预订人数
attendees: [123, 456, 789] // 参与人员ID
}
}
當有人報名時,可以更新這個課程:
var result = db.class.findAndUpdate(
query: {
_id: ObjectId("58e9f6cd58d2c10959c8619a"),
qty: {$lte: 50} // 保证已报名人数小于50时才报名
},
update: {
$inc: {
"reservations.qty": 1 // 报名人数+1
},
$push: {
"reservations.attendees": 102 // 新报名人员ID
}
}
});
也就是說,按照課程ID來找出這個課程,報名人數小於指定的數量時,會把新的報名人加進去,否則不會做任何更改。那麼該如何判斷報名是否成功呢? findAndModify
預設會傳回修改之前的文件(也可以傳回修改之後的文件)。所以:
if (result.reservations.qty < 50) {
// 报名成功
} else {
// 报名失败
}
關於findAndModify
的用法请参考db.collection.findAndModify()。MongoDB中对一个文档的修改具备原子性,所以不难发现update
也可以很好地完成上述任务。关于update
和findAndUpdate
的用法請參考db.collection.findAndModify()。 MongoDB中對一個文件的修改具備原子性,所以不難發現update
也可以很好地完成上述任務。關於update
和findAndUpdate
的比較,可以參考:Compares with update Method