2011-06-21 15 views
31

私はgmailとfacebookのようなスレッド型のメッセージシステムを作成しています。受信ボックスには最新のメッセージの件名、送信者名、タイムスタンプ。ここでfacebookとgmailのようなスレッドプライベートメッセージングシステムを作成する

は私のテーブルが設定されている方法は次のとおりです。

users: 
    user_id 
    user_name 

thread: 
    thread_id 
    title 
    to_id 
    to_keep 
    to_read 
    from_id 
    from_keep 
    date 

message: 
    message_id 
    thread_id 
    to_id 
    from_id 
    message_text 
    date 

私が今やっているユーザーが新しいメッセージを作成するとき、それはスレッドテーブルに新しいスレッドを作成し、その中に新しいメッセージユーザーがスレッドに応答すると、to_idfrom_idを交換し、それに基づいて新しいメッセージを作成する点を除き、現在のスレッドをスレッドテーブルに複製します。

また、受信トレイビューでは、user_idに基づいてすべてのスレッドを照会することができます。 SELECT * FROM thread WHERE to_id = 2 and to_keep = TRUE ORDER BY date DESCのようなもの、または送信トレイにメッセージを表示したい場合はSELECT * FROM thread WHERE from_id = 2 and from_keep = TRUE ORDER BY date DESCのようなものになります。

新しいメッセージがあるときにユーザーがスレッドを開くと、to_readはtrue UPDATE thread SET to_read = TRUE WHERE thread_id = 4に更新されます。

私はこのプロセスを複雑にしすぎていると感じており、これを行うにはより良い方法があるはずです。

ご意見やご感想をお寄せください。

このようにして、スレッドテーブルからすべてを選択してから、必要なものすべてを表示するためにユーザーテーブルを使用して結合します。しかし、私はこれを行うより良い方法があるように感じる。

+3

なぜスレッドはto_idとfrom_idを必要としますか?メッセージは、送信者と受信者を結びつけるものです。スレッドはメッセージのコンテナです。あるいは私は誤解していますか? –

+0

いいえ、あなたは正しいです。受信トレイにあるすべてのスレッドとスレッド内の最新のメッセージからの情報だけを選択してクエリを実行するのは難しいことでした。それは理にかなっていますか? – bigmike7801

答えて

45

メッセージの関係を各メッセージのユーザーの見解から分離しないのはなぜですか?

メッセージで自己参照関係でスレッディングを行います。言い換えると、メッセージには「responding_to_message_id」という列があります。

"to_id"がある理由がわかりません。メッセージは個々のユーザーに向けられていますか?これは非常に限られているようです。受信者がいない(受信者は誰でも読むことができるメッセージボード)か、電子メールの場合と同様に複数の受信者を指定できると思います。おそらく、システムの使用方法についてもっと詳しく説明できます。

あなたが掲示板に投稿していることを前提とすると、「from」だけが重要であると仮定すると、スレッディングの自己参照関係を持つメッセージテーブルと、ユーザーテーブルと、交差テーブルユーザーとメッセージの間で、各ユーザーがどのメッセージを読み取ったかを格納します。

このようにして、ユーザーがメッセージを読んだかどうかを知りたい場合は、特定のメッセージの交差テーブルでユーザーIDを読み取ろうとします。 でない場合、そのユーザーはそのメッセージを読み取っていません。

単一の受信者にする場合はこのデザインが保持され、複数の受信者を使用する場合は、各メッセージの受信者一覧を保持するために交差テーブルを使用できます。受信者の交差テーブルを持っている場合は、読み取りステータステーブルと二重の義務を果たすことができます。

EDIT:ERDスケッチ:ここ

は私が話しているかの迅速なスケッチです...送信者がメッセージを維持することを選択したか否かは、

ERD Sketch

は、メッセージ自体にフラグを立てています。メッセージが新しいスレッドの開始である場合、reply_to_message_id列はNULLです。それ以外の場合は、親メッセージのmessage_idです。受信者がメッセージを読むときに日付と時刻を追跡する機能と同様に、メッセージを保持する能力を持つ複数の受信者が存在する可能性があります。

EDIT 2:代替ERDと最新のメッセージ

@OPの問い合わせは、スレッド内の最新のメッセージを照会する方法を尋ねました。答えはスレッドの形式に依存します。すべてのメッセージがリニアストリームのメッセージの最後に行く平坦なスレッドを持つことも、スレッドのルートでない限り、各メッセージが特定の親を持つツリー状のスレッドを持つこともできます。上のERDでは、reply_to_message_idフィールドはいずれの方法でも使用できます。スレッドがフラットな場合、FKは常にルートMESSAGEになります。スレッドがツリー形である場合、FKは返信メッセージの直接の親に向かう。

実行する典型的なクエリが「スレッド内の最新のメッセージは何ですか?」です。そして、あなたのスレッドが、あなたはこのようにSQLを使用することができ、平坦である:

select top 1 
    M.message_id 
, M.sent_datetime 
, M.title 
, M.message_text 
, S.user_id 
, S.user_name 
-- and anything else you want... 
from MESSAGE M inner join USER S 
    on M.sender_user_id = U.user_id 
where M.reply_to_message_id = @ThreadRootMessageID 
order by 
    M.sent_datetime desc 

、一方で、あなたのスレッドはツリー型であり、これはあなたが迅速かつ容易に実行できるようにしたいクエリの場合は、上記のERDのスキーマはあまりにも簡単ではありません。 SQLはツリーでは良くありません。あなたは非正規化の少しで問題を解決することができます。 1 FKがルートを表示するには直接の親と1本のFKを表示するために今があることを

Tree Thread ERD

注:以下のERDを参照してください。スレッドは編集の対象ではないため、少なくともメッセージのルートが異なるスレッドを指し示すように変更された場合、これに伴う非正規化は更新アノーマリのリスクを意味しないので、冗長性はあまり問題になりません。

このERDを使用した場合、「スレッドXの最新のメッセージ」のクエリは上記と同じですが、M.reply_to_message_idではなくwhere句にM.thread_root_message_idを使用したクエリです。

+0

こんにちはJoel、テーブルをセットアップする方法を教えてもらえますか?ありがとう! – bigmike7801

+0

私はあなたの貢献に感謝しますが、スレッドメッセージをどのように作成するのか分かりません。例えば、1つのスレッドに対して5つのメッセージバックと4つ目のメッセージが存在する可能性があります。それは理にかなっていますか? – bigmike7801

+1

メッセージID 1はreply_to_message_id = nullです。メッセージID2はreply_to_message_id = 1である。メッセージID3はreply_to_message_id = 2であり、以下同様である。スレッドは、その親を指す各子メッセージによって定義されます。スレッドの最初のメッセージには親がありません。すべての返信は行います。送信者(MESSAGE.sender_user_id)または送信されたもの(RECIPIENTを介して参加)としてそれらを指し示すメッセージのいずれかです。 sender_keep/recipient_keepは「読み取りとしてマークする」機能です。メッセージ間の関係は、それらを視覚的にスレッドにソートするために使用されます。 –

関連する問題