检查是否可以预订
我目前正在实施预订系统。卖方可以指定给定类型的商品数量。规则很简单:永远没有比可用项目更多的预订。
现在,我想找出一个新的预订有多少个现有预订发生冲突,以检查是否已达到限制。
下图应该使您对我正在尝试做的事情有一些了解。
在此示例中,同时预订的最大数量为2。您可以看到已经有3个预订。其中之一未指定结束日期。仅查看现有的预订,那时的预订永远不会超过2个。
现在,我想检查是否可以进行新的预订。我知道每次预订的开始日期。对于没有指定结束日期的预订,结束日期将为null。
我正在尝试使用猫鼬实现这一目标。
没有关于此问题的现有代码。
分别查看每个示例:第一个没有结束日期的示例应该会失败,因为在07日和09日之间一次将有3个预订。第二个应该很好,因为在6日只有一个预订。
回答如下:我们将从找到与newDocument的所有交集开始,我只会做一个假设,即键入“ newBooking
” endDate
为date
(如果为null,那么我们将其设为非常未来日期)
let newBookingStartDate = newBooking.startDate;
let newBookingEndDate = newBooking.endDate ? newBooking.endDate : new Date().setYear(3000);
现在查询:
let results = await db.collection.aggregate([
{
$addFields: {
tmpEndDate: {
$cond: [
{$ne: ["$endDate", null]},
"$endDate",
newBookingEndDate
]
}
}
},
{
$match: {
$or: [
{
$and: [
{
startDate: {$lt: newBookingStartDate},
},
{
tmpEndDate: {$gt: newBookingStartDate}
},
]
},
{
$and: [
{
startDate: {$gte: newBookingStartDate},
},
{
startDate: {$lt: newBookingEndDate}
},
]
},
],
}
},
])
我们通过分为两种情况来匹配文档:
document.startDate
低于newDocument.startDate
-在这种情况下,我们需要检查document.endDate
是否大于newDocument.startDate
,如果大于,则我们有一个交集document.startDate
大于或等于newDocument.startDate
-在这种情况下,我们只需要检查document.startDate
小于newDocument.endDate
,然后再次得到一个交集
现在,我们需要遍历找到的文档并通过运行相同的查询来计算它们之间的交集:
for (let i = 0; i < results.length; i++) {
let doc = results[i];
let otherIds = results.map(val => val._id);
let docStartDate = doc.startDate;
let docEndDate = doc.endDate ? doc.endDate : new Date().setYear(3000);
let count = await db.collection.aggregate([
{
$match: {
_id: {$in: otherIds}
}
},
{
$addFields: {
tmpEndDate: {
$cond: [
{$ne: ["$endDate", null]},
"$endDate",
docEndDate
]
}
}
},
{
$match: {
$or: [
{
$and: [
{
startDate: {$lt: docStartDate},
},
{
tmpEndDate: {$gt: docStartDate}
},
]
},
{
$and: [
{
startDate: {$gte: docStartDate},
},
{
startDate: {$lt: docEndDate}
},
]
},
],
}
},
{
$count: "count"
}
])
if (count[0].count > 4){
return false;
}
}
如果任何计数结果为4或更大(4,因为我没有从数组中删除curr文档ID,它将始终与自身相交)