Reputation: 702
I'm designing a website where people can book for events. The schema that I have designed, has some concurrency issues. Let me show the schema first:
{
title: String,
pricing: { [
data: Date,
package: String,
price: Number
] },
availability: { [
date: Date,
capacity: Number, // Number of users a vendor can take.
booked: Number // Number of users booked the event for the date.
] }
}
Now an event's prices are unique by Date
and Package
. So a same date can have multiple prices if the package is different.
And the availability is unique by Date
only. So I have to create a separate object for that.
Problem
The problem is, I have two different calls.
booked
the same)booked
by 1 for a particular date)Since both resides in the same object, I think I will have a big concurrency issue in future because, if I save availability and at the same time users books the same event, the booked
number might not be correct.
Is there a better solution?
Upvotes: 1
Views: 123
Reputation: 2636
I'm assuming your post to update capacity from the client is something like
{
id: ObjectId //Your event Id
updates [
{date: Date, capacity: newCapacity},
{date: Date, capacity: newCapacity}
]
}
You could keep the arrays how they currently are but you should be trying to target just the capacity property instead of overwriting the whole document. The query below will iterate through the post and update the availablity
array targeting just the first item in the array that matches the query. I'm assuming javascript as the backend here but the idea is the same. If you have a lot of updates I would look into using bulkUpdate
for performance
for(var i = 0; i < updates.length; i++) {
var update = updates[i];
db.collection.update(
{
_id: update.id,
"availability.date": update.date
},
{$set: {"availability.$.capacity": update.capacity}}
)
}
for updating booked
for(var i = 0; i < updates.length; i++) {
var update = updates[i];
db.collection.update(
{
_id: update.id,
"availability.date": update.date
},
{"availability.$.booked": {$inc : 1}}
)
}
EDIT Example using bulk operation
var bulk = db.collection.initializeUnorderedBulkOp();
for(var i = 0; i < updates.length; i++) {
var update = updates[i];
bulk.find(
{
_id: update.id,
"availability.date": update.date
}).update({$set: {"availability.$.capacity": update.capacity}})
)
}
bulk.execute();
Upvotes: 1