Дизайн базы данных для повторяющихся событий с исключениями

Я создаю систему, которая должна хранить / управлять различными типами событий. Для простоты я сосредоточусь на разработке календаря (я создаю что-то немного другое, но календарь - хорошая аналогия, и его легко рассуждать). Я хотел бы услышать о возможных идеях дизайна базы данных / схемы.

Описание проблемы

У меня есть календарь с разными типами событий (для простоты скажем, что есть только один тип событий: Задача). Пользователь может добавить новое событие для определенной даты, отредактировать (изменить некоторые детали, например заголовок или перейти к другой дате) или удалить. Могут быть разовые события и повторяющиеся события (с разными типами повторения: каждые X дней, каждый 15-й день месяца, каждую неделю в понедельник; вроде как простой cron). Когда пользователь перемещает повторяющееся событие, все другие экземпляры этого события перемещаются таким же образом (например, +3 дня). Важная часть: повторяющиеся события могут иметь исключения. Так, например, предположим, что у меня есть повторяющееся событие A, которое повторяется каждые 7 дней. Но я хочу изменить его дату на следующую неделю, чтобы вместо вторника он был назначен на пятницу, после этого это все еще будет происходить во вторник. Это «исключительное» событие не должно изменяться при перемещении «родительского» события.

Кроме того, каждое повторяющееся событие может содержать дополнительную информацию, относящуюся только к 1 конкретному экземпляру, например: у меня одно и то же повторяющееся событие A повторяется каждые 7 дней, я хочу добавить примечание для экземпляра этой недели с надписью «X» и Я хочу добавить еще одно примечание для события A в следующем месяце, в котором написано «Y» - эти поля видны только этим отдельным экземплярам.

Идеи

Система с регулярными одноразовыми событиями довольно проста, поэтому я не буду обсуждать это и сосредоточусь только на повторяющихся событиях.

1. Одним из возможных решений является то, что напоминает ООП: я могу иметь Event "класс" с такими полями, как start_date, end_date (может быть null), recurrence_type (что-то вроде перечисления с возможными значениями EVERY_X_DAYS , DAY_OF_WEEK, DAY_OF_MONTH) и recurrence_value (скажем, 7). Когда пользователь добавляет новое повторяющееся событие, я просто создаю такое Event в базе данных. Когда пользователь хочет изменить 1 вхождение этого события, я добавляю новую запись в БД типа / класса MovedEvent, которая "наследуется" от Event с другой датой и имеет дополнительное поле related_to, которое указывает на ID (или UUID, если хотите ) из Event, к которому это относится. Но в то же время мне нужно отслеживать все MovedEvent (в противном случае на одной неделе было бы отображено 2 события), поэтому мне нужен массив moved_events из ID, указывающих на все MovedEvent. Недостаток: каждый раз, когда я хочу отобразить календарь, мне нужно получать Event и выбирать все события из moved_events, что не оптимально, если у меня будет много перемещенных событий.

2. Другой вариант - хранить каждое событие как отдельную запись. ИМО, это ужасная идея, но я упоминаю об этом только потому, что это возможно. Недостатки: каждый раз, когда я хочу отредактировать главное событие (например: я хочу изменить событие с «каждые 7 дней» на «каждые 9 дней»), мне нужно изменить каждое отдельное появление мероприятие. Однако «исключения» (изменение одного экземпляра) проще.

SQL / NoSQL? Детали весов

Я использую PostgreSQL в своем проекте, но у меня есть базовые знания о базах данных NoSQL, и если они лучше подходят для такого рода проблем, я могу его использовать.

Масштаб: Допустим, у меня 5 тыс. Пользователей, и у каждого будет в среднем 150 событий в неделю, 40% из которых могут быть «исключениями». Поэтому я хочу сделать эту систему эффективной.

Похожие вопросы и другие ресурсы

Я только что начал читать «Повторяющиеся события для календарей» Мартина Фаулера (http://martinfowler.com/apsupp/recurring.pdf), но я не уверен, применимо ли это к моей проблеме, и если да, то как можно разработать схему базы данных в соответствии с этим документом (предложения приветствуются).

Есть похожие вопросы, но я не встречал упоминания об «исключениях» (изменение одного экземпляра события без влияния на другие), но, возможно, кому-то эти ссылки пригодятся:

Извините за длинный вопрос, я хотел хорошо описать проблему. Тем не менее, я считаю, что это довольно хаотично, поэтому, если у вас есть дополнительные вопросы, я с радостью предоставлю более подробную информацию. Опять же, я хотел бы услышать о возможных идеях дизайна базы данных / схемы, а также о любых других предложениях. Спасибо!


person iyn    schedule 02.06.2015    source источник
comment
поделитесь своим опытом, как вы в итоге реализовали этот или несколько советов по реализации.   -  person user3775217    schedule 18.04.2017
comment
Здравствуйте, я тоже занимаюсь этой проблемой. Я решил пойти с грубым решением отдельных записей событий для каждого повторяющегося события. В моей системе событий есть такие действия, как RSVP, платежи и комментарии, отдельно для каждого события, и каждое событие должно иметь собственный уникальный идентификатор события с наивысшим приоритетом. Уже одно это упрощает мой выбор, я должен хранить каждое событие отдельно. С другой стороны, моя пользовательская активность происходит всего несколько месяцев за раз, поэтому я могу создать правило автоматического истечения срока действия (например, максимум 3 месяца), которое позволит контролировать время обработки БД.   -  person MarsAndBack    schedule 26.09.2017


Ответы (1)


Используйте iCalendar RRules и ExDates

Если это повторяющееся событие, просто сохраните дату начала и окончания, а также RRules и ExDates для события.

Используйте материализованное представление для предварительного расчета предстоящих фактических событий, скажем, на следующие 30 или 365 дней.

Поскольку вы используете Postgres, вы можете использовать существующие библиотеки RRule python, perl или javascript (например, ) внутри функции pg для расчета будущих событий на основе rrules и exdates

ОБНОВЛЕНИЕ: проверьте расширение pg_rrule: https://github.com/petropavel13/pg_rrule

person Neil McGuigan    schedule 02.06.2015
comment
ExRules устарели в RFC 5455 (ссылка на него). ExDates теперь используются для создания исключений из RRules. ExDate, однако, не поддерживается pg_rrule на момент написания этого комментария. По этому поводу есть открытая проблема - person austinian; 29.10.2015
comment
Я натыкаюсь на ваш комментарий 4 года спустя, и мне жаль, что я не нашел его две недели назад. - person Ege Ersoz; 13.09.2019