14

Google カレンダーに似たものを作成する必要があるため、ユーザーのすべてのイベントを含むイベント テーブルを作成しました。

難しいのは、繰り返し発生するイベントを処理することです。イベント テーブルの行には、イベントの種類を示す event_type フィールドがあります。これは、イベントが単一の日付のみ、または x 日ごとに繰り返し発生するイベントであるためです。 .

主な設計課題は、繰り返し発生するイベントの処理です。

ユーザーが月のビューを使用してカレンダーを表示する場合、特定の月のすべてのイベントを表示するにはどうすればよいですか? クエリは複雑になるので、別のテーブルを作成して、再発するイベントを含むすべてのイベントの行を作成する方が簡単だと思いました。

皆さんはどう思いますか?

4

16 に答える 16

5

前に述べたように、車輪の再発明はせず、ただそれを強化するだけです。

VCalendarをチェックアウトしてください。これはオープンソースであり、PHP、ASP、およびASP.Net(C#)で提供されます。

また、Asp.Net2.0で記述されたカレンダーを提供するDayPilotをチェックすることもできます。彼らはあなたがチェックアウトできるライトバージョンを提供します、そしてそれがあなたのために働くならば、あなたはライセンスを購入することができます。

更新(2009年9月30日):

もちろんホイールが壊れていない限り!また、必要に応じて、光沢のある新しいペイントを塗ることもできます(つまり、UIを改善します)。ただし、カレンダーシステムは(繰り返しイベントを使用すると)扱いにくい場合があり、何千回も行われているため、少なくとも基盤を構築するようにしてください。

于 2008-08-15T21:22:01.520 に答える
5

すべてのイベントの各インスタンスを保存しようとすると、非常に問題があり、不可能に思えます。誰かが「毎週木曜日に永久に」発生するイベントを作成した場合、将来のすべてのイベントを保存できないことは明らかです。

将来のイベントをオンデマンドで生成し、将来のイベントを表示したり、通知を送信したりする必要がある場合にのみ、将来のイベントを設定することができます。ただし、とにかく「オンデマンド」生成コードをビルドする場合は、常にそれを使用しないでください。イベント テーブルから取得し、オンデマンド イベント生成を使用してテーブルにまだ追加されていない新しいイベントを入力する代わりに、オンデマンド イベント生成のみを使用します。最終結果は同じになります。このスキームでは、開始日と終了日、およびイベントの頻度のみを保存する必要があります。

オンデマンドのイベント生成を回避する方法が見当たらないため、イベント テーブルにユーティリティが表示されません。キャッシングのためにそれが必要な場合は、間違ったアプローチを取っていると思います。第一に、とにかくオンデマンドのイベント生成を避けることができないため、これは貧弱なキャッシュです。第二に、とにかくより高いレベルでキャッシュする必要があります。キャッシュする場合は、イベントではなく、生成されたページをキャッシュします。

ポーリングをより効率的にする限り、15 分ごとにポーリングするだけで、データベースやサーバーが負荷を処理できない場合は、すでに運命にあります。汗をかくことなく、はるかに頻繁なポーリングを処理できない場合、データベースがユーザーを処理できる方法はありません。

于 2008-08-15T20:06:09.863 に答える
4

私はまさにこの問題に取り組んでおり、このスレッドを読むまではiCalendarrfc 2445 )の間隔を完全に空けていたので、これがどれだけうまく統合されるか、統合されないかはわかりません。とにかく、私がこれまでに思いついたデザインは次のようになります。

  • 繰り返し発生するイベントのすべてのインスタンスを、少なくとも発生する前に保存することはできないため、イベントの最初のインスタンスを実際の日付、オプションの有効期限、およびnull許容のrepeat_unitフィールドとrepeat_incrementフィールドとして格納するテーブルが1つあります。繰り返しを説明します。単一インスタンスの場合、repitionフィールドはnullです。それ以外の場合、単位は「日」、「週」、「月」、「年」になり、増分は、次の発生の開始日に追加する単位の倍数になります。
  • 過去のイベントを保存することは、モデル内の他のエンティティとの関係を確立する必要がある場合にのみ有利であるように思われます。その場合でも、すべての場合に明示的な「イベントインスタンス」テーブルを用意する必要はありません。他のエンティティがすでに日付/時刻の「インスタンス」データを持っている場合は、イベントへの外部キー(または多対多の場合は結合テーブル)で十分である可能性があります。
  • 「このインスタンスを変更する」/「将来のすべてのインスタンスを変更する」を行うために、私はイベントを複製し、古いイベントを期限切れにすることを計画していました。したがって、単一のインスタンスを変更するには、最後のオカレンスで古いインスタンスを期限切れにし、変更を加えて繰り返しなしで新しい一意のオカレンスのコピーを作成し、次のオカレンスで元のインスタンスの別のコピーを作成します。将来。今後のすべてのインスタンスの変更も同様です。元のインスタンスを期限切れにして、変更と繰り返しの詳細を含む新しいコピーを作成するだけです。

これまでのところ、この設計で見られる2つの問題は次のとおりです。

  1. MWFタイプのイベントを表現するのが難しくなります。可能ですが、ユーザーはM、W、Fで毎週繰り返される3つの個別のイベントを作成する必要があり、必要な変更はそれぞれ個別に行う必要があります。これらの種類のイベントは私のアプリでは特に有用ではありませんが、モデルに疣贅を残し、私が望むよりも普遍性が低くなります。
  2. イベントをコピーして変更を加えることで、イベント間の関連付けを解除できます。これは、一部のシナリオで役立つ場合があります(または、場合によっては問題が発生する可能性があります)。理論的には、イベントテーブルに「copied_from」idフィールドを含めて、イベントが始まったのですが、そのようなものがどれほど役立つかを十分に考えていませんでした。一つには、親子の階層関係はSQLからクエリを実行するのが面倒なので、そのデータをクエリするコストを上回るメリットはかなり重い必要があります。代わりにネストされたセットを使用することもできます。

最後に、ストレートSQLを使用して特定の期間のイベントを計算することは可能だと思いますが、正確な詳細を把握していないため、クエリは通常、煩雑すぎて価値がないと思います。ただし、議論のために、次の式を使用して、特定の月とイベントの年との間の月の差を計算できます。

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

最後の例に基づいて、MODを使用して、月の差が正しい倍数であるかどうかを判断できます。

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

とにかく、これは完璧ではありません(期限切れのイベントを無視しない、イベントの開始/終了時間を考慮しないなど)ので、やる気を起こさせる例としてのみ意図されています。一般的に言って、ほとんどのクエリは複雑になりすぎると思います。おそらく、特定の範囲内で発生するイベント、または範囲の前に期限切れにならないイベントを照会し、SQLではなくコードでインスタンス自体を計算する方がよいでしょう。本当にデータベースに処理を実行させたい場合は、ストアドプロシージャを使用すると、作業が大幅に楽になります。

于 2008-08-22T22:19:10.480 に答える
3

ical標準から始めましょう。これをモデルとして使用すると、Google カレンダー、Outlook、Mac ical (プログラム) のすべてを実行でき、それらとほぼ瞬時に統合できます。

そこから、大量の ajax と javascript なしでは、ドラッグ ドロップと複数のカレンダーを備えた派手な Web UI を持つことはできないので、ajax と javascript を骨抜きにする時間です。

于 2008-08-15T19:14:02.950 に答える
2

強引な方法ですが、それでも合理的な方法は、繰り返し発生するイベントのすべてのインスタンスについて、単一のイベントテーブルに新しい行を作成することです。すべて、シリーズの前のイベントではなく、シリーズの最初のイベントを指します。これにより、親IDに基づいて選択できるため、特定のシリーズのすべての要素の選択や削除が簡単になります。また、ユーザーは、残りのアイテムに影響を与えることなく、シリーズから個々のアイテムを削除できます。

このクエリは、要素3から始まるシリーズを取得します。

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

今月のすべてのアイテムを取得するには、イベントテーブルに開始日と終了日があると仮定して、次のことを行う必要があります。

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

シリーズの作成/変更をプログラムで処理することはそれほど難しいことではありませんが、実際には、提供する機能セットと、それがどのように使用されるかによって異なります。シリーズとイベントを区別したい場合は、イベントに個別のシリーズテーブルとnull許容のseries_idを設定して、シリーズの制御を維持しながら、個々のイベントを自由に操作できるようにすることができます。

于 2008-08-16T04:40:32.290 に答える
2

開始日、終了日、および有効期限が必要です。1 日イベントの開始日と終了日は同じで、部分的な日イベントを行うこともできます。繰り返し発生するイベントについては、開始日と終了日は同じ日ですが、時間が異なる場合は、繰り返しの頻度 (毎日、毎週、毎月など) を指定する列挙またはテーブルがあります。

これにより、毎日の場合は「このイベントは毎日発生します」、毎週の場合は「このイベントは毎週 2 日に発生します」、毎月の場合は「毎月 5 日にこのイベントが発生します」、「このイベントは次の日に発生します毎年の 215 日」は、その日付が有効期限よりも前である限り、毎年使用されます。

于 2008-08-15T19:20:32.610 に答える
2

ダレン、

これが実際にイベント テーブルを設計した方法ですが、考えてみると、イベントを作成した 10 万人のユーザーがいるとします。イベント (イベントは 1 日の特定の時間でも可能です!) であるため、このテーブルを 15 分ごとにポーリングする可能性があります!

これが、すべてのイベント/再発生イベントを展開する別のテーブルを作成したかった理由です。このようにして、複雑なクエリやビジネス ロジックを実行することなく、そのテーブルに簡単にアクセスして、ユーザーのイベントの月のビューを取得できます。ポーリングもはるかに効率的になります。

問題は、このセカンダリ テーブルを翌日または翌月に使用する必要があるかどうかです。もっと理にかなっていることは何ですか?ユーザーが表示できる最大数は月のビューであるため、特定の月のすべてのイベントを書き出すテーブルに傾倒しています。

(もちろん、ユーザーが元のイベント テーブルを編集する可能性があるため、このセカンダリ テーブルを維持する必要があります)。

ちゃんちゃん、

実際には同じ種類の機能を使用して設計しましたが、イベントを保存する方法、特に繰り返し発生するイベントを処理する方法について言及しているだけです。

于 2008-08-15T19:27:27.290 に答える
1

過去の経験から、発生するイベントごとに新しいレコードを作成し、前のイベントを参照する列を作成して、一連のすべてのイベントを追跡できるようにします。

これには 2 つの利点があります。

  1. 次のイベント日を決めるための複雑なルーチンはありません
  2. 残りの部分に影響を与えることなく、個々の発生を編集できます

これがあなたの思考の糧になることを願っています:)

于 2008-08-15T19:19:04.890 に答える
1

これらのものを保存する方法については、ical仕様を読むことについて@ChanChanに同意する必要があります。再発、特に例外のある再発を処理する簡単な方法はありません。これを処理するためにデータベースを構築し、再構築し、再構築しましたが、ical に戻ってきます。

ユースケースによっては、従属テーブルを作成することは悪い考えではありません。発生時刻を正確に計算するためのアルゴリズム。. . ええと、発生します。. . 実際には非常に複雑になる可能性があります。実行することから逃れることはできませんが、結果をキャッシュすることを検討する価値があります。

于 2008-08-15T19:22:35.397 に答える
1

@ゲートキラー

個々のオカレンスを編集するケースは考えていませんでした。その場合、オカレンスを個別に保存することは理にかなっています。

しかし、その場合、どのくらい先のイベントを保存するのでしょうか? 任意の日付を選択しますか? ユーザーが将来の月/年に初めてアクセスしたときに、新しい発生を自動生成しますか?

また、ユーザーがシリーズ全体を編集したい場合は、どのように処理しますか。「毎週火曜日の朝 10 時 30 分にミーティングを行っていましたが、水曜日の 8 時にミーティングを開始する予定です。」

于 2008-08-15T19:25:04.720 に答える
0

これが実際にイベントテーブルを設計した方法ですが、イベントを作成した10万人のユーザーがいるとすると、このテーブルはかなり大きな打撃を受けます。特に、人々に彼らのことを思い出させるためにメールを送信する場合はそうです。イベント(イベントは1日の特定の時間に発生する可能性もあります!)なので、15分ごとにこのテーブルをポーリングする可能性があります。

データベースはデータセットを処理する例外ジョブを実行するので、私はそれについてあまり心配しません。これをプライマリテーブルとして使用し、イベントの有効期限が切れたら、それらを別のテーブル(アーカイブなど)に移動する必要があります。

次に試してみたいのは、データベースへのクエリをできるだけ少なくすることです。そのため、情報をキャッシング層(velocityなど)に移動し、データをデータベースに保持します。

次に、スケーリングの目的で、情報を複数のデータベースに分割できます。つまり、ユーザー1〜10000のカレンダーはサーバー1に存在し、10001〜20000はサーバー2に存在します。

それが私がこのようなソリューションをスケーリングする方法ですが、それでも私が提案した元のソリューションが進むべき道だと思います。それはあなたがそれをどのようにスケーリングするかが問題になります。

于 2008-08-16T04:22:20.503 に答える
0

未定義の書き込み:

…このテーブルはかなり大きな打撃を受けるでしょう。特に、イベントを人々に思い出させるためにメールを送信する場合(イベントは1日の特定の時間帯でもかまいません!)、15分ごとにこのテーブルをポーリングする可能性があります。 !!

通知用のテーブルを作成します。それだけをポーリングします。

イベント(定期的またはその他)が更新されたときに通知テーブルを更新します。

編集:それが懸念される場合、データベースビューは通常のフォームに違反しない可能性があります。ただし、送信された通知と、まだどこかに送信されていない通知を追跡することをお勧めします。

于 2008-08-15T21:44:55.423 に答える
0

2 番目の段落は、イベントの発生ごとに行を持つ 2 番目のイベント テーブルを検討していることを意味していると思います。私はそれを避けます。

繰り返し発生するイベントには、開始日と終了日を指定する必要があります (X 日ごとに「永久に」継続するイベントの場合は Null になる可能性があります)。許可する頻度の種類を決定する必要があります。毎月 N 日、特定の平日など

私はおそらく 2 つのテーブルを使用する傾向があります。1 つは 1 回限りのイベント用で、もう 1 つは定期的なイベント用です。2 つを別々に照会して表示する必要があります。

私がこれに取り組むつもりなら (そして、この車輪の再発明を避けるためにできる限りの努力をします)、私はオープンソースのライブラリを探すか、少なくとも、あなたが見ることができるカレンダーを備えたオープンソースのプロジェクトを探します. . おすすめはありますか?

于 2008-08-15T19:17:51.803 に答える
0

Derek Park、私はテーブル内のイベントのすべてのインスタンスを作成し、このテーブルは毎月再生成されます (したがって、「永久に」再発するように設定されたイベントは、Windows サービスまたは Windows サービスを使用して 1 か月前に再生成されます)。おそらくSQLサーバーレベルで)。ポーリングは 15 分ごとに行われるだけでなく、電子メール通知に関連するポーリングのみの場合もあります。誰かが 1 か月間のイベントを表示したい場合、すべてのイベントと繰り返し発生するイベントを取得し、どのイベントを表示するかを判断する必要があります (繰り返し発生するイベントは 6 か月前に作成された可能性があるため、ユーザーが表示している月)。

ザック、私はデータベースを完全に正規化することにはあまり関心がありません。セカンダリ テーブルを作成することを考えているという事実は、すでにルールの 1 つを破っています。私のコアデータベーステーブルは「ルール」に従っていますが、パフォーマンスが向上する場合は、セカンダリテーブル/列を作成してもかまいません。

于 2008-08-15T22:08:13.627 に答える
0

誰かが Ruby をやっているなら、この種のことをする素晴らしいライブラリ Runt があります。チェックアウトする価値があります。 http://runt.rubyforge.org/

于 2009-02-01T17:15:07.417 に答える
0

Ra-Ajax カレンダー スターター キットには、特定の日付を変更できる RenderDate イベントを処理するサンプルが含まれています。「定期的なイベント」はアルゴリズム的なものですが、ここでは、役立つカレンダーはほとんどないと思います...

于 2008-11-25T01:01:24.437 に答える