我有一个事件模式:

owner: {
    type: Schema.Types.ObjectId,
    ref: 'User',
    required: true
},
participants: [
    {
        type: Schema.Types.ObjectId,
        ref: 'User'
    }
],
createdOn: { type: Date, default: Date.now },
lastModified: { type: Date, default: Date.now },
active:{ type: Boolean, default: false },
eventDate: { type: Date },
startAt: { type: Date },
endAt : { type: Date },
timeZone:{ type: 'String', required: true }


我想插入事件,以使事件不会与其他事件重叠(例如:如果某个事件发生在2018-2-14,开始于3:00 am,结束于4:00 am,则此日期之间不应有任何事件3:00 AM和4:00 AM(此事件除外),但在该日期可能会有其他时段的事件,但不在3:00 AM到4:00 AM之间)

我尝试了以下逻辑,但似乎没有用。这个逻辑有什么问题:

const eventData = {
    owner: req
        .body
        .owner
        .trim(),
    startAt: setTimeToDate(req.body.eventDate, req.body.startAt.trim(), req.body.timeZone),
    endAt: setTimeToDate(req.body.eventDate, req.body.endAt.trim(), req.body.timeZone),
    eventDate: moment(req.body.eventDate).toISOString(),
    participants: req.body.participants,
    active: true,
    timeZone: req.body.timeZone
};

Events.find({
    $and: [
        {
            "eventDate": new Date(eventData.eventDate)
        }, {
            $or: [
                {
                    $and: [
                        {
                            "startAt": {
                                $lt: new Date(eventData.startAt)
                            }
                        }, {
                            "startAt": {
                                $lte: new Date(eventData.endAt)
                            }
                        }
                    ]
                }, {
                    $and: [
                        {
                            "endtAt": {
                                $gte: new Date(eventData.startAt)
                            }
                        }, {
                                "endtAt": {
                                    $gt: new Date(eventData.endAt)
                                }
                            }
                        ]
                }
                ]
        }

        ]
})
    .exec(function (err, results) {
        const count = results.length;
        if (!count) {
            const newEvent = new Events(eventData);
            newEvent.save((err) => {
                if (err) {
                    res
                        .status(400)
                        .json({success: false, message: 'Could not create this availability.'});
                }
                res
                    .status(200)
                    .send({success: true, message: 'Your availability on this date is created successfully.'});
            });
        }

    });

最佳答案

好吧,我不确定,但我发现逻辑上有两个缺陷

基本上,您需要在新的startAt和endAt之间具有startAt或endAt的任何记录

在第一种情况下,您需要在新的startAt和endAt之间具有startAt时间的插槽,因此逻辑将是

startAt greater than new startAt and less than equal to new endAt
$and: [
                    {
                        "startAt": {
                            $gt: new Date(eventData.startAt)
                        }
                    }, {
                        "startAt": {
                            $lte: new Date(eventData.endAt)
                        }
                    }
                ]


另外,您想要在新的startAt之后和新的endAt之前具有endAt的记录,因此对于该逻辑

endAt greater than new startAt and less than equal to new endAt
    $and: [
                        {
                            "endAt": {
                                $gt: new Date(eventData.startAt)
                            }
                        }, {
                            "endAt": {
                                $lte: new Date(eventData.endAt)
                            }
                        }
                    ]


我认为这会起作用。

编辑好第三个条件是,在新StartAt之前开始并在新EndAt之后结束的插槽,因为它们不会落入上述条件

  $and: [
                            {
                                "startAt": {
                                    $lt: new Date(eventData.startAt)
                                }
                            }, {
                                "endAt": {
                                    $gt: new Date(eventData.endAt)
                                }
                            }
                        ]

10-06 02:30