[英]Mongodb/mongoose query for completely overlapping dates (that could span multiple documents)
我在设计处理重叠日期的查询时遇到了一些问题。
所以这是场景,我不能透露太多关于实际项目的信息,但这里有一个类似的例子。 假设我有一个FleaMarket
。 它有一堆关于它自己的数据,比如name
、 location
等。
因此,一个FleaMarket
将有许多Stalls
,可用来预订全年的一部分(如短至2天,只要全年的那种东西)。 因此, FleaMarket
需要指定一年内的开放时间。 大多数场景要么全年开放,要么整个夏季/秋季开放,但可能会进一步细分(因为季节决定定价)。 每个FleaMarket
将定义自己的Seasons
,其中将包括一个startDate
和endDate
(含一年)。
这是一个用于建模此示例的 ERD:
当用户尝试预订Stall
,他们已经选择了FleaMarket
(尽管理想情况下,根据未来的可用性进行搜索会很好)。 很容易判断是否已在要求的日期预订了Stall
:
bookings = await Booking.find({
startDate: { $lt: <requested end date> },
endDate: { $gt: <requested start date> },
fleaMarketId: <flea market id>,
}).select('stallId');
bookedIds = bookings.map(b => b.stallId);
stalls = await Stall.find({
fleaMarketId: <flea marked id>,
_id: { $nin: bookedIds }
});
我遇到的问题是确定是否有Stall
可用于指定的Season
。 问题是 2 个季节可能是连续的,因此您可以进行跨 2 个季节的预订。
我最初尝试过这样的查询:
seasons = await Season.find({
fleaMarketId: <flea market id>,
startDate: { $lt: <requested end date> },
endDate: {$gt: <requested start date> }
});
然后以编程方式检查任何返回的季节是否是连续的,并从所有季节都存在的摊位中挑选可用的摊位。 但不幸的是,我刚刚意识到如果请求的日期仅与一个季节部分重叠,这将不起作用(例如:请求Jan 1 2020 - Jan 10 2020
,但该季节定义为Jan 2 2020 - May 1 2020
)
有没有办法检查可能与多个文档重叠的完全重叠的日期? 我正在考虑计算和存储当前和未来可用的季节日期(存储为总范围)在Stall
上非规范化。
在这一点上,我几乎在想我需要对架构进行相当多的重构。 有什么建议吗? 我知道这看起来非常相关,但应用程序中的其他几乎所有地方都没有真正处理这些关系。 正是这种搜索是相当有问题的。
更新:
我只是想到可能会创建某种Calendar
文档,可以存储FleaMarket
的集中可用性列表,这将进行滚动更新以仅存储未来和当前数据,并慢慢擦除历史数据,或者可能将其存档以不同的格式。 也许这会解决我的问题,我将很快与我的团队讨论。
因此,正如我在帖子的更新中所说,我想出了创建滚动日历的想法。
对于任何有兴趣的人,这是我得到的:
我创建了一个Availability
集合,其中包含如下文档:
{
marketId: ObjectId('5dd705c0eeeaf900450e7009'),
stallId: ObjectId('5dde9fc3bf30e500280f80ce'),
availableDates: [
{
date: '2020-01-01T00:00:00.000Z',
price: 30.0,
seasonId: '5dd708e7534f3700a9cad0e7',
},
{
date: '2020-01-02T00:00:00.000Z',
price: 30.0,
seasonId: '5dd708e7534f3700a9cad0e7',
},
{
date: '2020-01-03T00:00:00.000Z',
price: 35.0,
seasonId: '5dd708e7534f3700a9cad0e8',
}
],
bookedDuring: [
'2020-01-01T00:00:00.000Z'
'2020-01-02T00:00:00.000Z'
]
}
然后处理此集合的更新:
四季
摊位
预订
bookedDuring
bookedDuring
添加或删除日期然后要查找市场的可用摊位,您可以查询 where { marketId: /* market's ID */, availableDates.date: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
然后取出stallId
要查找可用的市场,请执行{ availableDates.dates: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
选择不同的marketIds
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.