sql - 为有异常(exception)的重复事件设计的数据库

标签 sql database database-design calendar recurring-events

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

问题描述

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

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

创意

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

1. 一种可能的解决方案是类似于 OOP 的解决方案:我可以拥有一个 Event带有字段的“类”,例如 start_date , end_date (可以是 null )、recurrence_type (类似于枚举,可能的值为 EVERY_X_DAYSDAY_OF_WEEKDAY_OF_MONTH )和 recurrence_value (比如 7 )。当用户添加新的重复事件时,我只是创建这样的 Event在数据库中。当用户想要更改此事件的 1 次发生时,我将新条目添加到类型/类 MovedEvent 的数据库中。 “继承”自 Event具有不同的日期并具有附加字段 related_to指向 ID (或 UUID ,如果你愿意) Event它与之相关。但与此同时,我需要跟踪所有 MovedEvent s(否则我会在同一周显示 2 个事件),所以我需要一个数组 moved_eventsID s 指向所有 MovedEvent s。
缺点 : 每次我想显示日历我都需要得到Event并从 moved_events 中选择所有事件,如果我有很多移动的事件,这不是最佳选择。

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

SQL/NoSQL?秤详情

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

规模:假设我有 5000 个用户,每个用户平均每周有 150 个事件,其中 40% 可以是“异常(exception)”。因此我想设计这个系统是高效的。

类似问题和其他资源

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

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

  • Design question: How would you design a recurring event system?
  • Optimal design for a Database with recurring event
  • Design option for 'recurring tasks'
  • Calendar Recurring/Repeating Events - Best Storage Method
  • What is the best way to represent "Recurring Events" in database?

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

    最佳答案

    使用 iCalendar规则和 ExDates

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

    使用物化 View 预先计算即将发生的实际事件,比如接下来的 30 天或 365 天。

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

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

    关于sql - 为有异常(exception)的重复事件设计的数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30603864/

    相关文章:

    sql - 如何在SQL Server中选择列名中带有特殊字符的列?

    sql - 在 Oracle 中准确计算过去的年数(考虑闰年)

    mysql - JOIN 语句中双嵌套派生表中的未知列

    mysql - 根据列值显示不同的枚举以供选择

    python - SqlAlchemy 中的动态表创建和 ORM 映射

    php - 如何从sql中以逗号分隔的表中检索数据?

    mysql - 如何在同一个查询中添加多个聚合函数的结果?

    MySQL MASTER TO MASTER 复制在数据库级别工作,但不使用 Spring/Hibernate 在应用程序级别工作

    database - 在数据库列中存储分隔列表真的那么糟糕吗?

    database - 提供多版本数据库以向后兼容生产应用程序/数据库