12

我正在构建一个需要存储/管理不同类型事件的系统。为简单起见,我将专注于设计日历(我正在构建一些稍微不同的东西,但日历是一个很好的类比,而且很容易推理)。我想听听可能的数据库/模式设计理念。

问题描述

我有一个包含不同类型事件的日历(为简单起见,假设只有一种类型的事件:任务)。用户可以为特定日期添加新事件、编辑(更改一些细节,如标题或移动到另一个日期)或删除。可以有一次性事件和重复事件(具有不同类型的重复:每 X 天、每月第 15 天、每周星期一;有点像简单的 cron)。当用户移动重复事件时,该事件的所有其他实例都以相同的方式移动(例如:+3 天)。重要部分:重复事件可以有例外。因此,例如,假设我有一个周期性事件 A,它每 7 天重复一次。但是我想将它的日期更改为下周,所以它被分配到星期五而不是星期二,之后它仍然会在星期二发生。这个“例外”

此外,每个重复事件都可以包含仅与 1 个特定实例相关的附加信息,例如:我有相同的重复事件 A 每 7 天重复一次,我想为本周实例添加一个注释,上面写着“X”,并且我想为下个月的事件 A 添加另一个注释,上面写着“Y” - 这些字段仅对该单个实例可见。

想法

具有定期、一次性事件的系统非常简单,所以我不会讨论这个,只关注重复事件。

1.一种可能的解决方案是类似于 OOP 的解决方案:我可以有一个Event“类”,其中包含诸如start_date, end_date(can be null)、recurrence_type(类似于 enum 的可能值为EVERY_X_DAYS, DAY_OF_WEEK, DAY_OF_MONTH) 和recurrence_value(say 7) 的字段。当用户添加新的重复事件时,我只是Event在数据库中创建这样的。当用户想要更改此事件的 1 次发生时,我将新条目添加到从不同日期MovedEvent“继承”的类型/类的数据库中,并具有指向它的(或,如果你愿意的话)的附加字段相关。但与此同时,我需要跟踪所有Eventrelated_toIDUUIDEventMovedEvents(否则我会在同一周显示 2 个事件),所以我需要一个指向所有smoved_events的s 数组。 缺点:每次我想显示日历时,我都需要从中获取并选择所有事件,如果我有很多移动的事件,这不是最佳选择。IDMovedEventEventmoved_events

2.另一个想法是将每个事件存储为单独的记录。IMO 这是一个糟糕的主意,但我只是提到它是因为它是一种可能性。缺点:每次我想编辑主要事件(例如:我想将事件从“每 7 天”更改为“每 9 天”)时,我都需要更改事件的每一次发生。不过,“例外”(更改单个实例)更容易。

SQL/NoSQL?比例细节

我在我的项目中使用 PostgreSQL,但我对 NoSQL 数据库有基本的了解,如果它们更适合此类问题,我可以使用它。

规模:假设我有 5k 个用户,每个用户平均每周有 150 个事件,其中 40% 可能是“例外”。因此,我想设计这个系统是高效的。

类似问题和其他资源

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

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

抱歉问了一个很长的问题,我想很好地描述这个问题。然而,我觉得这很混乱,所以如果你有其他问题,我会很乐意提供更多细节。同样,我想听听可能的数据库/模式设计理念以及任何其他建议。谢谢!

4

1 回答 1

8

使用iCalendar RRules 和 ExDates

如果它是重复事件,只需存储该事件的开始/结束日期时间和 RRules 和 ExDates。

使用物化视图预先计算即将发生的实际事件,例如未来 30 天或 365 天。

当您使用 Postgres 时,您可以在 pg 函数中使用现有的 python、perl 或 javascript RRule 库(例如dateutil)来根据 rrules 和 exdates 计算未来事件

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

于 2015-06-02T20:23:25.103 回答