Разработка календарной системы, такой как Календарь Google

Мне нужно создать нечто похожее на Календарь Google, поэтому я создал таблицу событий, содержащую все события для пользователя.

Жесткая часть обрабатывает повторяющиеся события, строка в таблице событий имеет поле event_type, в котором указывается, какое событие оно есть, поскольку событие может быть только для одной даты или повторного события каждые x дней.

Основная задача дизайна - обработка повторных событий.

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

Что вы, ребята, думаете?

Ответ 1

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

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

Я не вижу никакого способа избежать генерации события по требованию, поэтому я не вижу утилиту в таблице событий. Если вы хотите это ради кэширования, то я думаю, что вы принимаете неправильный подход. Во-первых, это плохой кеш, потому что вы все равно не можете избежать генерации событий по требованию. Во-вторых, вы, вероятно, должны быть кешированием на более высоком уровне. Если вы хотите кэшировать, то кешируйте созданные страницы, а не события.

Что касается повышения эффективности вашего опроса, если вы проводите только опрос каждые 15 минут, и ваша база данных и/или сервер не могут справиться с нагрузкой, то вы уже обречены. Нет никакой возможности, чтобы ваша база данных могла обрабатывать пользователей, если она не может обрабатывать много, гораздо более частый опрос, не нарушая пота.

Ответ 2

Как уже говорилось, не изобретать колесо, просто улучшите его.

Оформить заказ VCalendar, это с открытым исходным кодом и поставляется в PHP, ASP и ASP.Net(С#)!

Также вы можете проверить Day Pilot, который предлагает календарь, написанный в Asp.Net 2.0. Они предлагают облегченную версию, которую вы можете проверить, и если она сработает для вас, вы можете приобрести лицензию.

Обновление (9/30/09):

Если, конечно, колесо не сломано! Кроме того, вы можете поместить блестящий новый слой краски, если хотите (т.е. Сделать лучший интерфейс). Но, по крайней мере, попытайтесь найти какую-то основу для строительства, поскольку система календаря может быть сложной (с повторением событий), и это было сделано тысячи раз.

Ответ 3

Я бы сказал, начните с стандартного стандарта. Если вы используете его как свою модель, вы сможете делать все, что Google Calendar, Outlook, Macic (программа) и получить практически мгновенную интеграцию с ними.

Оттуда, время до костей на вашем аяксе и javascript, потому что у вас не может быть flashy web ui с перетаскиванием и несколькими календарями без тонны ajax и javascript.

Ответ 4

Даррен,

Вот как я создал таблицу событий на самом деле, но, думая об этом, скажу, что у меня есть 100K пользователей, которые создают события, эта таблица будет сильно ударить, особенно если я собираюсь отправлять электронные письма, чтобы напомнить люди их событий (события могут быть и для определенного времени дня!), поэтому я мог бы опросить эту таблицу каждые 15 минут, возможно!

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

Вопрос в том, должна ли эта вторичная таблица быть на следующий день или месяц? Что имеет смысл? Поскольку максимальный пользователь может просматривать в течение нескольких месяцев, я склоняюсь к таблице, которая записывает все события за определенный месяц.

(конечно, мне придется поддерживать эту дополнительную таблицу для любых изменений, которые пользователь может внести в таблицу исходных событий).

ChanChan,

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

Ответ 5

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

В этом запросе вы получите серию, которая начинается с элемента 3:

SELECT * FROM events WHERE id = 3 OR parentid = 3

Чтобы получить все предметы за этот месяц, если у вас есть дата начала и дата окончания в таблице событий, все, что вам нужно сделать, это:

SELECT * FROM events WHERE startdate >= '2008-08-01' AND enddate <= '2008-08-31'

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

Ответ 6

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

Это имеет два преимущества:

  • Сложные процедуры для разработки следующей даты события
  • Индивидуальные вхождения можно редактировать без использования остальных

Надеюсь, это даст вам пищу для размышлений:)

Ответ 7

У вас должна быть дата начала, дата окончания и срок действия. Однодневные события будут иметь одинаковую дату начала и дату окончания, а также позволяют выполнять частичные дневные события. Что касается повторных событий, то дата начала и окончания будет в тот же день, но будет иметь разные времена, тогда у вас есть перечисление или таблица, которая указывает частоту повторения (ежедневно, еженедельно, ежемесячно и т.д.).

Это позволяет говорить, что "это событие появляется каждый день" ежедневно, "это событие появляется во второй день недели" для еженедельника, "это событие появляется в 5-й день каждого месяца" для ежемесячного ", это событие появляется в 215-й день каждого года" в течение года, пока дата меньше даты истечения срока действия.

Ответ 8

Я должен согласиться с @ChanChan по чтению iical spec для того, как хранить эти вещи. Нет простого способа справиться с рецидивами, особенно с исключениями. Я создал и перестроил и перестроил базу данных, чтобы справиться с этим, и я продолжаю возвращаться к ical.

Неплохая идея создать подчиненную таблицу, в зависимости от вариантов использования. Алгоритм для вычисления точно при вхождении., um, происходят., действительно может быть довольно сложным. Там не уходит от запуска, но стоит подумать о кешировании результатов.

Ответ 9

@GateKiller

Я не думал о том, где вы редактируете отдельные события. Имеет смысл, что в этом случае вы будете хранить события отдельно.

Если вы это сделаете, то как далеко в будущем вы будете хранить события? Вы выбираете произвольную дату? Вы автоматически генерируете новые события в первый раз, когда пользователь просматривает будущие месяцы/годы?

Также, как вы обрабатываете случай, когда пользователь хочет редактировать всю серию. "У нас было собрание каждое утро вторника в 10:30, но мы собираемся начать заседание в среду в 8 часов"

Ответ 10

Я решаю именно эту проблему, и я полностью отстал iCalendar (rfc 2445) до чтения этой темы, поэтому я понятия не имею, насколько это будет или не будет интегрироваться с этим. В любом случае дизайн, который я придумал, выглядит примерно так:

  • Вы не можете хранить все экземпляры повторяющегося события, по крайней мере, до того, как они произойдут, поэтому у меня просто есть одна таблица, в которой первый экземпляр события хранится как фактическая дата, необязательное истечение и значение nullable repeat_unit и repeat_increment, чтобы описать повторение. Для отдельных экземпляров поля повторения являются нулевыми, иначе единицы будут "день", "неделя", "месяц", "год", а приращение - это просто количество единиц для добавления к дате начала следующего события.
  • Сохранение прошлых событий кажется только выгодным, если вам нужно установить отношения с другими объектами в вашей модели, и даже тогда нет необходимости иметь явную таблицу событийных событий в каждом случае. Если у других объектов уже есть данные "экземпляра" даты и времени, то скорее всего будет достаточно внешнего ключа для события (или таблицы соединения для многих-ко-многим).
  • Чтобы сделать "изменить этот экземпляр" / "изменить все будущие экземпляры", я планировал просто дублировать события и истекать устаревшие. Таким образом, чтобы сменить один экземпляр, вы истекаете старый в последнем случае, создаете копию для нового уникального события с изменениями и без повторения, а другую копию оригинала в следующем случае, повторяющееся в будущее. Изменение всех будущих экземпляров аналогично, вы просто закончите оригинал и сделаете новую копию с изменениями и деталями реплики.

Две проблемы, которые я вижу с этим дизайном:

  • Это приводит к тому, что события типа MWF трудно представлять. Это возможно, но заставляет пользователя создавать три отдельных события, которые повторяются еженедельно на M, W, F индивидуально, и любые изменения, которые они хотят сделать, также должны выполняться по каждому отдельно. Такие события не особенно полезны в моем приложении, но он оставляет бородавку на модели, которая делает ее менее универсальной, чем хотелось бы.
  • Скопировав события для внесения изменений, вы нарушите связь между ними, что может быть полезно в некоторых сценариях (или, может быть, это будет просто проблематично). В таблице событий теоретически может содержаться поле id "copied_from", где происходило событие, но я не полностью понял, насколько это возможно. С одной стороны, иерархические отношения между родителями и детьми - это боль для запроса из SQL, поэтому преимущества должны быть довольно тяжелыми, чтобы перевесить затраты на запрос этих данных. Вы можете использовать вложенный набор, я полагаю.

Наконец, я думаю, что можно вычислить события за определенный промежуток времени, используя прямой SQL, но я не разработал точные детали, и я думаю, что запросы обычно оказываются слишком громоздкими, чтобы быть полезными. Однако для аргумента вы можете использовать следующее выражение для вычисления разницы в месяцах между данным месяцем и годом события:

(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12))

Основываясь на последнем примере, вы можете использовать MOD, чтобы определить, является ли разница в месяцах правильной кратной:

MOD(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12), repeatIncrement) = 0

В любом случае это не идеально (он не игнорирует истекшие события, не учитывает время начала и окончания события и т.д.), поэтому это означает только мотивирующий пример. Вообще говоря, хотя я думаю, что большинство запросов будут слишком сложными. Вероятно, вам лучше опросить события, которые происходят во время заданного диапазона, или не истекать до диапазона, и вычислять сами экземпляры кода, а не SQL. Если вы действительно хотите, чтобы база данных выполняла обработку, тогда хранимая процедура, вероятно, упростит вашу жизнь.

Ответ 11

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

Повторяющиеся события должны иметь дату начала и дату остановки (которая может быть Null для событий, которые продолжаются каждые X дней "навсегда" ). Вам нужно будет решить, какую частоту вы хотите разрешить - каждый X дней, N-го числа каждого месяца, каждого буднего дня и т.д.

Я бы, скорее всего, склонялся к двум таблицам - один за один раз, а второй - к повторяющимся событиям. Вам придется запросить и отобразить два отдельно.

Если бы я собирался заняться этим (и я старался изо всех сил, чтобы избежать повторного использования этого колеса), я бы поискал библиотеки с открытым исходным кодом или, по крайней мере, проекты с открытым исходным кодом с календарями, которые вы может посмотреть. Любые рекомендации ребята?

Ответ 12

undefined написал:

& hellip; эта таблица будет удалена довольно трудно, особенно если я собираюсь рассылка электронных писем, чтобы напомнить людям о их события (события могут быть для конкретное время суток!), поэтому я могу опросить эту таблицу каждые 15 минут.

Создайте таблицу для уведомлений. Опросите только это.

Обновить таблицу уведомлений при обновлении событий (повторяющихся или иным образом).

EDIT: просмотр базы данных может не нарушать нормальные формы, если это вызывает беспокойство. Но вы, вероятно, захотите отслеживать, какие уведомления были отправлены и которые еще никуда не отправлены.

Ответ 13

Дерек Парк, Я буду создавать каждый экземпляр события в таблице, и эта таблица будет регенерироваться каждый месяц (так что любое событие, которое было настроено на повторную запись "навсегда", будет регенерировано за один месяц вперед, используя службу Windows или, возможно, sql server). Опрос будет проводиться не только каждые 15 минут, это может быть только для опросов, связанных с уведомлениями по электронной почте. Когда кто-то хочет просмотреть свои события в течение месяца, мне придется собирать все свои события и повторять события и выяснять, какие события будут отображаться (поскольку повторное происшествие могло быть создано 6 месяцев назад, но относится к в месяц, который пользователь просматривает).

Зак, я не слишком обеспокоен наличием полностью нормализованной базы данных, тот факт, что я думаю о создании вторичной таблицы, уже нарушает один из правил хе-хе. Мои основные таблицы базы данных следуют "правилам", но я не возражаю против создания вторичных таблиц/столбцов в моменты, когда это приносит пользу в отношении производительности.

Ответ 14

Вот как я создал таблицу событий на самом деле, но, думая об этом, скажу, что у меня есть 100K пользователей, которые создают события, эта таблица будет сильно ударить, особенно если я собираюсь отправлять электронные письма, чтобы напомнить люди их событий (события могут быть и для определенного времени дня!), поэтому я мог бы опросить эту таблицу каждые 15 минут, возможно!

Базы данных выполняют задания исключения для обработки наборов данных, поэтому я не стал бы слишком беспокоиться об этом. То, что вам нужно сделать, это использовать это как свою основную таблицу, а затем, когда события истекают, переместите их в другую таблицу (например, архив).

Следующее, что вы хотите попробовать, - это как можно меньше запросить db, поэтому переместите информацию в уровень кэширования (например, speed) и просто сохраняйте данные в базе данных.

Затем вы можете разделить информацию по нескольким базам данных для масштабирования. т.е. пользователи 1-10000 календарей существуют на сервере 1, 10001 - 20000 существуют на сервере 2 и т.д.

Вот как я бы масштабировал такое решение, но я все же думаю, что оригинальное решение, которое я предложил, - это способ пойти, это просто, как вы масштабируете его, что становится вопросом.

Ответ 15

Календарный стартовый комплект Ra-Ajax содержит образец обработки события RenderDate, который может модифицировать даты специально. Хотя "повторяющиеся события" - скорее алгоритмическая вещь, и здесь я сомневаюсь, что очень мало календарей вам очень помогут...

Ответ 16

Если кто-то делает Ruby, там отличная библиотека Runt, которая делает это. Стоит проверить. http://runt.rubyforge.org/