[英]Mongodb/mongoose query for completely overlapping dates (that could span multiple documents)
I'm having some issues designing a query that deals with overlapping dates.我在设计处理重叠日期的查询时遇到了一些问题。
So here's the scenario, I can't reveal too much about the actual project but here is a similar example.所以这是场景,我不能透露太多关于实际项目的信息,但这里有一个类似的例子。 Lets say I have a
FleaMarket
.假设我有一个
FleaMarket
。 It has a bunch of data about itself such as name
, location
, etc.它有一堆关于它自己的数据,比如
name
、 location
等。
So a FleaMarket
would have many Stalls
, that are available to be booked for a portion of the year (as short as 2 days, as long as all year sort of thing).因此,一个
FleaMarket
将有许多Stalls
,可用来预订全年的一部分(如短至2天,只要全年的那种东西)。 So the FleaMarket
needs to specify when in a year it will be open.因此,
FleaMarket
需要指定一年内的开放时间。 Most scenarios would either be open all year, or all summer/fall, but it could possible be broken down further (because seasons determine pricing).大多数场景要么全年开放,要么整个夏季/秋季开放,但可能会进一步细分(因为季节决定定价)。 Each
FleaMarket
would define their Seasons
which would include a startDate
and endDate
(including year).每个
FleaMarket
将定义自己的Seasons
,其中将包括一个startDate
和endDate
(含一年)。
Here's an ERD to model this example:这是一个用于建模此示例的 ERD:
When a user attempts to book a Stall
, they have already selected a FleaMarket
(although ideally it would be nice to search based on availability in the future).当用户尝试预订
Stall
,他们已经选择了FleaMarket
(尽管理想情况下,根据未来的可用性进行搜索会很好)。 It's really easy to tell if a Stall
is already booked for the requested dates:很容易判断是否已在要求的日期预订了
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 }
});
The issue I'm having is determining if a Stall
is available for the specified Season
.我遇到的问题是确定是否有
Stall
可用于指定的Season
。 The problem comes that 2 seasons could be sequential, so you could make a booking that spans 2 seasons.问题是 2 个季节可能是连续的,因此您可以进行跨 2 个季节的预订。
I originally tried a query like so:我最初尝试过这样的查询:
seasons = await Season.find({
fleaMarketId: <flea market id>,
startDate: { $lt: <requested end date> },
endDate: {$gt: <requested start date> }
});
And then programatically checked if any returned seasons were sequential, and plucked the available stalls from that that existed in all seasons.然后以编程方式检查任何返回的季节是否是连续的,并从所有季节都存在的摊位中挑选可用的摊位。 But unfortunately I just realized this won't work if the requested date only partially overlaps with a season (ex: requested
Jan 1 2020 - Jan 10 2020
, but the season is defined as Jan 2 2020 - May 1 2020
)但不幸的是,我刚刚意识到如果请求的日期仅与一个季节部分重叠,这将不起作用(例如:请求
Jan 1 2020 - Jan 10 2020
,但该季节定义为Jan 2 2020 - May 1 2020
)
Is there a way I can handle checking for completely overlapping dates that could possible overlap with multiple documents?有没有办法检查可能与多个文档重叠的完全重叠的日期? I was thinking about calculating and storing the current and future available season dates (stored as total ranges) denormalized on the
Stall
.我正在考虑计算和存储当前和未来可用的季节日期(存储为总范围)在
Stall
上非规范化。
At this point I'm almost thinking I need to restructure the schema quite a bit.在这一点上,我几乎在想我需要对架构进行相当多的重构。 Any recommendations?
有什么建议吗? I know this seems very relational, but pretty much everywhere else in the application doesn't really do much with the relationships.
我知道这看起来非常相关,但应用程序中的其他几乎所有地方都没有真正处理这些关系。 It's just this search that is quite problematic.
正是这种搜索是相当有问题的。
Update :更新:
I just had the thought of maybe creating some sort of Calendar
Document that can store a centralized list of availability for a FleaMarket
, that would do a rolling update to only store future and present data, and slowly wiping away historical data, or maybe archiving it in a different format.我只是想到可能会创建某种
Calendar
文档,可以存储FleaMarket
的集中可用性列表,这将进行滚动更新以仅存储未来和当前数据,并慢慢擦除历史数据,或者可能将其存档以不同的格式。 Perhaps this will solve my issue, I will be discussing it with my team soon.也许这会解决我的问题,我将很快与我的团队讨论。
So as I said in an update in my post, I came up with the idea to create a rolling calendar.因此,正如我在帖子的更新中所说,我想出了创建滚动日历的想法。
For anyone who is interested, here's what I got:对于任何有兴趣的人,这是我得到的:
I created an Availability
collection, that contains documents like the following:我创建了一个
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'
]
}
Then handling updates to this collection:然后处理此集合的更新:
Seasons四季
Stalls摊位
Bookings预订
bookedDuring
bookedDuring
bookedDuring
bookedDuring
添加或删除日期Then to find available stalls for a market, you can query where { marketId: /* market's ID */, availableDates.date: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
and then pluck out the stallId
然后要查找市场的可用摊位,您可以查询 where
{ marketId: /* market's ID */, availableDates.date: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
然后取出stallId
And to find markets that have available, do { availableDates.dates: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
select distinct marketIds
要查找可用的市场,请执行
{ availableDates.dates: { $all: [/* each desired day */], bookedDuring: { $nin: [/* same dates */ ] } }}
选择不同的marketIds
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.