繁体   English   中英

Mongodb/mongoose 查询完全重叠的日期(可以跨越多个文档)

[英]Mongodb/mongoose query for completely overlapping dates (that could span multiple documents)

我在设计处理重叠日期的查询时遇到了一些问题。

所以这是场景,我不能透露太多关于实际项目的信息,但这里有一个类似的例子。 假设我有一个FleaMarket 它有一堆关于它自己的数据,比如namelocation等。

因此,一个FleaMarket将有许多Stalls ,可用来预订全年的一部分(如短至2天,只要全年的那种东西)。 因此, FleaMarket需要指定一年内的开放时间。 大多数场景要么全年开放,要么整个夏季/秋季开放,但可能会进一步细分(因为季节决定定价)。 每个FleaMarket将定义自己的Seasons ,其中将包括一个startDateendDate (含一年)。

这是一个用于建模此示例的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM