【问题标题】:Check whether or not a booking is possible检查是否可以预订
【发布时间】:2019-10-03 16:24:27
【问题描述】:

我目前正在实施预订系统。卖家可以指定有多少给定类型的物品可用。规则很简单:预订数量永远不会超过可用物品数量。

现在我想知道有多少现有预订与新预订有冲突,以检查是否已达到限制。

下图应该让您对我正在尝试做的事情有所了解。

https://ibb.co/4pJk8XV

在此示例中,并发预订的最大数量为 2。如您所见,已经有 3 个预订。其中之一没有指定结束日期。 仅查看现有预订,当时绝不会超过 2 个预订。

现在我想检查是否可以进行新的预订。我知道每次预订的开始日期。对于没有指定结束日期的预订,结束日期将为空。

我正在尝试使用 Mongoose 来实现这一目标。

没有关于这个问题的现有代码。

分别查看每个示例:第一个没有结束日期的示例应该会失败,因为在 07 日和 09 日之间,一次会有 3 个预订。第二个应该没问题,因为 06 号只有一个现有预订。

【问题讨论】:

    标签: node.js mongodb typescript mongoose


    【解决方案1】:

    我们将从查找与 newDocument 的所有交集开始未来的日期)

    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}
                            },
                        ]
                    },
                ],
            }
        },
    ])
    

    我们通过分两种情况来匹配文档:

    1. document.startDate 低于newDocument.startDate - 在这种情况下,我们只需要检查document.endDate 是否大于newDocument.startDate,如果是则我们有一个交集

    2. 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 >= 3){
                return false;
          }
        }
    

    如果任何计数结果为 3 或更大(3 因为我没有从数组中删除当前文档 ID,并且它总是与自身相交)返回 false,因为插入新文档会使您超过阈值。

    【讨论】:

    • 嘿,听起来不错。但我认为仅仅找到交叉点是不够的,不是吗?例如,如果有 2 个现有预订,每个预订都与新预订有交集(一个在开始日期,一个在结束日期),上面的代码将返回 2。如果我们知道说我们一次只能有 2 个预订预订是不可能的。但事实是,预订是可能的,因为任何时候都不会超过 2 个预订。
    • 你是对的,我编辑我的答案是正确的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    • 2012-05-03
    • 2019-09-22
    • 1970-01-01
    相关资源
    最近更新 更多