具有异常情况的重复事件的数据库设计

15
我正在构建一个需要存储/管理不同类型事件的系统。为了简单起见,我将专注于设计日历(我正在构建稍微不同的东西,但是日历是一个很好的比喻,并且易于推理)。我想听听可能的数据库/模式设计想法。 问题描述 我有一个带有不同类型事件的日历(为简单起见,假设只有一种事件类型:任务)。用户可以为特定日期添加新事件、编辑(更改一些详细信息,如标题或移动到另一个日期)或删除事件。可以有一次性事件和重复事件(具有不同类型的重复:每X天,每月15日,每周星期一;类似于简单的cron)。当用户移动重复事件时,此事件的所有其他实例将以相同的方式移动(例如:+3天)。重要部分:重复事件可以有异常。因此,例如,假设我有一个重复事件A,它每7天重复一次。但是我想将其日期更改为下周,因此它将被分配给星期五,之后仍将在星期二发生。当“父”事件移动时,此“异常”事件不应受到影响。
此外,每个重复事件都可以有与仅与1个特定实例相关的其他信息,例如:我按照相同的规律每7天重复A事件,我想为这个星期实例添加一个注释,说“X”,并且我想为下个月的事件A添加另一个注释,说“Y” - 这些字段仅对该单个实例可见。 想法 具有常规一次性事件的系统非常简单,因此我不会讨论它,并仅关注重复事件。1. 一种可能的解决方案类似于OOP:我可以拥有一个Event“类”,其中包含像start_dateend_date(可以是null)、recurrence_type(类似于枚举,其可能值为EVERY_X_DAYSDAY_OF_WEEKDAY_OF_MONTH)和recurrence_value(如7)等字段。当用户添加新的重复事件时,我只需在数据库中创建这样的Event。当用户想要更改此事件的一个实例时,我会添加一个新的类型/类MovedEvent到数据库中,该类型/类“继承”自Event,日期不同并具有附加字段related_to,该字段指向与其相关的EventID(或者您愿意,则为UUID)。但同时,我需要跟踪所有的MovedEvent(否则,我将在同一周内显示2个事件),因此我需要一个数组moved_events,其中包含指向所有MovedEventIDs。 缺点:每次想要显示日历时我都需要获取Event并选择moved_events中的所有事件,如果我有很多移动事件,这不是最优的做法。 2. 另一个想法是将每个事件作为单独的记录存储。在我看来,这是一个可怕的想法,但我只是提及它因为它是一种可能性。 缺点:每次我想要编辑主要事件时(例如:我想将事件从“每7天”更改为“每9天”),我都需要更改每个事件的每个实例。虽然"例外"(更改单个实例)更容易。

SQL/NoSQL?比例细节

我在我的项目中使用PostgreSQL,但我对NoSQL数据库只有基础知识,如果它们更适合这种问题,我可以使用它。

规模:假设我有5k个用户,每个用户平均将有150个事件/周,其中40%可能是“异常”。 因此,我希望设计这个系统以高效运行。

类似的问题和其他资源

我刚开始阅读Martin Fowler的“日历中的重复事件”(http://martinfowler.com/apsupp/recurring.pdf),但我不确定它是否适用于我的问题,如果适用,如何根据此文档设计数据库架构(欢迎提出建议)。

有类似的问题,但我没有看到任何“异常”的提及(更改1个事件实例而不影响其他),但也许有人会发现这些链接有用:

抱歉问题比较长,我想要描述问题得更好。但是我感觉写得有点混乱,如果你有其他问题,我很乐意提供更多细节。再次感谢,我希望听到可能的数据库/模式设计想法和其他任何建议。


1
嘿,你能分享一下你是如何实现这个功能的经验或者提供一些实现的小技巧吗? - user3775217
1
你好,我也在处理这个问题。我决定采用直接的解决方案,为每个重复出现的事件单独创建事件条目。我的事件系统对于每个事件发生都有不同的活动,例如RSVP、支付和评论,而且每个事件发生都必须有自己独特的事件ID,最高优先级。这使得我的选择变得容易,我必须单独存储每个事件。另一方面,我的用户活动只会持续几个月,因此我可以制定一个自动过期规则(例如最多3个月),以保持数据库处理时间可管理性。 - Kalnode
1个回答

9

使用iCalendar的RRules和ExDates

如果这是一个重复事件,只需存储事件的开始/结束日期时间以及RRules和ExDates。

使用Materialized View预先计算即将到来的实际事件,比如未来30天或365天。

由于您正在使用Postgres,因此可以在pg函数中使用现有的python、perl或javascript RRule库(例如dateutil)根据RRules和ExDates计算未来事件。

更新:请查看pg_rrule扩展:https://github.com/petropavel13/pg_rrule


7
在链接的RFC 5455中,ExRules已被弃用。现在使用ExDates来创建RRules的例外。然而,在本篇评论撰写时,pg_rrule尚不支持ExDate。关于此问题有一个开放的问题(https://github.com/petropavel13/pg_rrule/issues/3)。 - austinian
3
我在四年后看到了你的评论,真希望我两周前就发现了它。 - Ege Ersoz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接