2011-01-24 10 views
10

Qual è la migliore struttura di tabella per memorizzare le finestre di dialogo tra gli utenti nei messaggi privati? Ogni utente può inviare messaggi personali a molti ricevitori. Ogni messaggio ha la bandiera per il mittente: si elimina un messaggio o meno Ogni messaggio ha la bandiera per la ricevente: è messaggio non letto, letto o cancellato Ogni messaggio può essere eliminato (insieme flag 'cancellato')struttura della tabella per i messaggi personali

pagina principale

PrivateMessages dovrebbero assomiglia a questo:

Ad esempio Utente1 invia Messaggio1 a Utente2 e Utente3. A pagina messaggio privato devo mostrare 2 stessi messaggi:

  1. inviato Message1 a user2
  2. inviato Message1 a USER3

prossimo passo - Utente2 risponde a Messaggio2, vedrò sul stessa pagina seguente:

  1. ricevuti Message2 da user2 (risposta su Message1)
  2. inviato Message1 a USER3

prossimo passo, rispondo a Message3, vedrò

  1. inviato Message3 a user2
  2. inviato Message1 a USER3

e così via.

Qualcuno può fornire una struttura da tavolo? Sto usando MySQL 5.5

Domanda principale. Come posso ottenere solo l'ultimo messaggio non cancellato di ogni finestra di dialogo?

UPD.

Ho bisogno di vedere sulla finestra di dialogo della pagina principale, tra utente corrente e altri utenti (con paginazione, ordinati per Data DESC).

+0

elemento lista 1 e 2 aspetto identico. Se user1 e user2 hanno scambiato PM con SubjectA e SubjectB, sarebbero due "dialoghi" separati, corretto? – PerformanceDBA

+0

Ogni nuovo messaggio avvia una nuova finestra di dialogo tra gli utenti. E ogni risposta al messaggio continua il dialogo. – Lari13

risposta

8

io risponderò alla tua domanda principale prima, quindi mostrare la struttura della tabella userò per questo.

di ottenere solo l'ultimo messaggio non cancellato di un particolare dialogo:

select 
    Message.Id 
    ,Message.Subject 
    ,Message.Content 
from Message 
join Junc_Message_To on Fk_Message = Message.Id 
where Junc_Message_To.Fk_User = {RECIPIENT_ID} 
    and Message.Fk_User__From = {SENDER_ID} 
    and Junc_Message_To.Deleted is null 
order by Junc_Message_To.Sent desc 
limit 1 

Una semplice struttura a tre tavolo potrebbe essere utilizzato.

Nella tabella 1 vengono memorizzati i record utente, un record per utente.

La tabella 2 memorizza il record di messaggio: un record per messaggio, la chiave esterna si riferisce all'utente che ha inviato il messaggio.

Nella tabella 3 è memorizzata la correlazione tra i messaggi e gli utenti a cui sono stati inviati i messaggi.

enter image description here

Ecco l'SQL utilizzata per creare il diagramma tabella precedente:

create table `User` (
    `Id`   int   not null auto_increment , 
    `Username`  varchar(32) not null , 
    `Password`  varchar(32) not null , 
    primary key  (`Id`) , 
    unique index  `Username_UNIQUE` (`Username` ASC)) 
engine = InnoDB 

create table `Message` (
    `Id`   int   not null auto_increment , 
    `Fk_User__From` int   not null , 
    `Subject`  varchar(256) not null , 
    `Content`  text   not null , 
    primary key (`Id`) , 
    index   `Fk_Message_User__From` (`Fk_User__From` ASC) , 
    constraint  `Fk_Message_User__From` 
    foreign key (`Fk_User__From`) 
    references `User` (`Id`) 
    on delete cascade 
    on update cascade) 
engine = InnoDB 

create table `Junc_Message_To` (
`Fk_Message`  int   not null , 
    `Fk_User`  int   not null , 
    `Sent`   datetime  not null , 
    `Read`   datetime  not null , 
    `Deleted`  datetime  not null , 
    PRIMARY KEY (`Fk_Message`, `Fk_User`) , 
    INDEX   `Fk_Junc_Message_To__Message` (`Fk_Message` ASC) , 
    INDEX   `Fk_Junc_Message_To__User` (`Fk_User` ASC) , 
    constraint  `Fk_Junc_Message_To__Message` 
    foreign key (`Fk_Message`) 
    references `Message` (`Id`) 
    on delete cascade 
    on update cascade, 
    constraint  `Fk_Junc_Message_To__User` 
    foreign key (`Fk_User`) 
    references `User` (`Id`) 
    on delete cascade 
    on update cascade) 
engine = InnoDB 
+0

Grazie. Non esattamente quello di cui ho bisogno, ma ho la giusta direzione per essere desiderata :) – Lari13

4

Ho fatto questo in passato con una tabella MessageRecipient che contiene semplicemente MessageID, ReceiverID e Status. Avevo FolderID anche in quella tabella, ma non hai quel requisito. La tabella dei messaggi non ha memorizzato alcuna informazione sul destinatario.

È un join per recuperare i messaggi degli utenti, ma impedisce la duplicazione dell'oggetto e del corpo del messaggio tra i destinatari.

+0

Ci ho pensato, ma dove memorizzare DialogID e come ottenere il valore DialogID. Voglio dire se user1 inizia una nuova finestra di dialogo con user2, dove ottenere valore per DialogID? O come legare tutti i post di un dialogo? – Lari13

+0

Come pensavi di mantenere DialogID con il modello a una tabella? –

+0

Non lo so :) Questa è la mia domanda in realtà :) – Lari13

1

Se fossi un architector DB, farei struttura come questa

CREATE TABLE statuses(
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    name VARCHAR(255) NOT NULL, 
    description VARCHAR(255) DEFAULT NULL, 
    PRIMARY KEY (id), 
    UNIQUE INDEX name (name) 
) 
ENGINE = INNODB 
CHARACTER SET utf8 
COLLATE utf8_general_ci; 

CREATE TABLE users(
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    name VARCHAR(255) NOT NULL, 
    PRIMARY KEY (id), 
    UNIQUE INDEX name (name) 
) 
ENGINE = INNODB 
CHARACTER SET utf8 
COLLATE utf8_general_ci; 

CREATE TABLE messages(
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
    reply_to INT(11) UNSIGNED NOT NULL, 
    sender INT(11) UNSIGNED NOT NULL, 
    recipient INT(11) UNSIGNED NOT NULL, 
    subject VARCHAR(255) DEFAULT NULL, 
    message TEXT DEFAULT NULL, 
    `time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (id), 
    INDEX FK_messages_messages_id (reply_to), 
    INDEX FK_messages_users_id_recipient (recipient), 
    INDEX FK_messages_users_id_sender (sender), 
    CONSTRAINT FK_messages_messages_id FOREIGN KEY (reply_to) 
    REFERENCES messages (id) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT FK_messages_users_id_recipient FOREIGN KEY (recipient) 
    REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION, 
    CONSTRAINT FK_messages_users_id_sender FOREIGN KEY (sender) 
    REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION 
) 
ENGINE = INNODB 
CHARACTER SET utf8 
COLLATE utf8_general_ci; 

CREATE TABLE messages_statuses(
    message_id INT(11) UNSIGNED NOT NULL, 
    status_id INT(11) UNSIGNED NOT NULL, 
    PRIMARY KEY (message_id, status_id), 
    INDEX FK_messages_statuses_statuses_id (status_id), 
    CONSTRAINT FK_messages_statuses_messages_id FOREIGN KEY (message_id) 
    REFERENCES messages (id) ON DELETE CASCADE ON UPDATE CASCADE, 
    CONSTRAINT FK_messages_statuses_statuses_id FOREIGN KEY (status_id) 
    REFERENCES statuses (id) ON DELETE CASCADE ON UPDATE CASCADE 
) 
ENGINE = INNODB 
CHARACTER SET utf8 
COLLATE utf8_general_ci; 

Io non vedo nulla di difficile qui, ma se avrete ottenuto tutte le domande (circa.) - si sentono liberi chiedere.

+0

Che cosa sono messages_statuses? Cosa c'è in questa tabella, se ogni messaggio può essere cancellato da ciascun utente? Voglio dire, ho per es. 5 messaggi nella finestra di dialogo tra utente1 e utente2. Utente1 elimina i messaggi 3 e 5 e Utente2 non elimina nulla? Cosa c'è in questa tabella? Come posso ottenere solo l'ultimo messaggio di ogni finestra di dialogo? – Lari13

3

Ecco il mio approccio a questo, in base alle informazioni fornite.

La tabella utente è un arrendersi. Il mio è solo id e name.

Ovviamente abbiamo bisogno di una tabella per archiviare i messaggi. Abbiamo bisogno di sapere chi author ed esso, il subject, il message contenuto e (probabilmente) quando era created/inviato.

Abbiamo bisogno di sapere chi sono i message_recipients. Tecnicamente anche lo message.author viene inviato una copia dello message (nella maggior parte dei casi), ma solitamente viene inserito in un folder='Sent'. Tutti gli altri probabilmente lo hanno nel loro folder="Inbox". Gli utenti possono quindi spostare il numero message nel loro folder='Trash' o eliminarlo completamente. Se per qualche motivo hai bisogno di conservare i messaggi dopo che l'utente li ha cancellati, puoi farlo creando folder='Deleted' con uno folder.type='System'. In caso contrario, eliminare il record nella tabella message_recipients per quello message_recipient.user.

Quindi ecco le informazioni per questo. Vedere i casi di test per l'interrogazione dopo lo schema e i dati.

schema:

SET FOREIGN_KEY_CHECKS=0; 

DROP TABLE IF EXISTS `user`; 
CREATE TABLE `user` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `name` tinytext NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; 

CREATE TABLE `message` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `author` int(11) unsigned NOT NULL, 
    `subject` varchar(255) NOT NULL, 
    `message` mediumtext NOT NULL, 
    `created` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `fk_m_author` (`author`), 
    CONSTRAINT `fk_m_author` FOREIGN KEY (`author`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; 

DROP TABLE IF EXISTS `message_folder_type`; 
CREATE TABLE `message_folder_type` (
    `name` varchar(40) NOT NULL, 
    `type` enum('System','User') NOT NULL DEFAULT 'User', 
    PRIMARY KEY (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

DROP TABLE IF EXISTS `message_recipient`; 
CREATE TABLE `message_recipient` (
    `message` int(11) unsigned NOT NULL, 
    `user` int(11) unsigned NOT NULL, 
    `folder` varchar(40) NOT NULL, 
    PRIMARY KEY (`message`,`user`), 
    KEY `fk_mr_user` (`user`), 
    KEY `fk_mr_message_folder` (`folder`), 
    CONSTRAINT `fk_mr_message_folder` FOREIGN KEY (`folder`) REFERENCES `message_folder_type` (`name`) ON UPDATE CASCADE, 
    CONSTRAINT `fk_mr_message` FOREIGN KEY (`message`) REFERENCES `message` (`id`) ON UPDATE CASCADE, 
    CONSTRAINT `fk_mr_user` FOREIGN KEY (`user`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

dati di test:

INSERT INTO `user` VALUES ('1', 'Bob'); 
INSERT INTO `user` VALUES ('2', 'Harry'); 
INSERT INTO `user` VALUES ('3', 'Salley'); 
INSERT INTO `user` VALUES ('4', 'Jim'); 
INSERT INTO `user` VALUES ('5', 'Jake'); 
INSERT INTO `user` VALUES ('6', 'Randall'); 
INSERT INTO `user` VALUES ('7', 'Ashley'); 

INSERT INTO `message` VALUES ('1', '4', 'Message 1', 'this is a message', '2011-03-01 15:47:07'); 
INSERT INTO `message` VALUES ('2', '2', 'Message 2', 'this is a reply to message 1', '2011-03-02 15:47:28'); 
INSERT INTO `message` VALUES ('3', '7', 'Message 3', 'another cool message', '2011-03-02 15:48:15'); 
INSERT INTO `message` VALUES ('4', '4', 'Message 4', 'blah blah blah Sally', '2011-03-09 15:48:43'); 

INSERT INTO `message_folder_type` VALUES ('Deleted', 'System'); 
INSERT INTO `message_folder_type` VALUES ('Inbox', 'User'); 
INSERT INTO `message_folder_type` VALUES ('Sent', 'User'); 
INSERT INTO `message_folder_type` VALUES ('Trash', 'User'); 

INSERT INTO `message_recipient` VALUES ('1', '1', 'Inbox'); 
INSERT INTO `message_recipient` VALUES ('1', '2', 'Inbox'); 
INSERT INTO `message_recipient` VALUES ('2', '4', 'Inbox'); 
INSERT INTO `message_recipient` VALUES ('2', '5', 'Inbox'); 
INSERT INTO `message_recipient` VALUES ('3', '5', 'Inbox'); 
INSERT INTO `message_recipient` VALUES ('1', '4', 'Sent'); 
INSERT INTO `message_recipient` VALUES ('2', '2', 'Sent'); 
INSERT INTO `message_recipient` VALUES ('3', '7', 'Sent'); 
INSERT INTO `message_recipient` VALUES ('4', '4', 'Sent'); 
INSERT INTO `message_recipient` VALUES ('1', '3', 'Trash'); 
INSERT INTO `message_recipient` VALUES ('4', '3', 'Trash'); 

Test Case: Prendi l'ultimo, non cancellato, il messaggio di ogni finestra

non sono completamente sicuro di ciò che significa, ma assumerò "in una determinata casella di posta dell'utente" e "non nella cartella di sistema eliminata" come parte della mia query.

SELECT message.`subject`, message.message, message.`author` 
    FROM message_recipient 
    INNER JOIN message ON message.id = message_recipient.message 
WHERE 
    message_recipient.user = 4 
    AND message_recipient.folder != 'Deleted' 
ORDER BY message.created DESC 

Questo dà, sulla base dei dati di test forniti, i seguenti risultati:

Subject   Message      Author 
Message 4  blah blah blah Sally   4 
Message 2  this is a reply to message 1 2 
Message 1  this is a message    4 
+0

Perché è stato downvoted? –

+0

Non da me :), sto cercando di capire, in che modo i messaggi sono collegati tra loro? Voglio dire, come posso sapere se il messaggio 999 risponde al messaggio 888 o no? Tra gli utenti possono esserci molti thread di messaggi. Ogni thread di messaggi è 'dialog' tra due utenti. Due utenti potrebbero avere un conteggio di finestre di dialogo. – Lari13

+0

@ Lari13, ha solo bisogno di tracciare la finestra di dialogo la prima volta (ad esempio questa risposta/foward proviene da questo messaggio) o per sempre (come gmail)? –

0
id* INT, sender_id INT, recipient_id INT, message TEXT, 
flag_s_deleted = 0 TINYINT, flag_r_deleted = 0 TINYINT, flag_r_read = 0 TINYINT, 
sent_datetime DATETIME 

"Come posso ottenere solo l'ultimo messaggio non cancellato di ogni finestra di dialogo? "

qui sei:

select * from (...) where 
(sender_id = ID1 and recipient_id = ID2 and flag_s_deleted = 0) 
or (sender_id = ID2 and recipient_id = ID1 and flag_r_deleted = 0) 
order by sent_date desc LIMIT 1 

ultimo messaggio tra l'utente (ID1) e altra persona (ID2)

-1
create database testMessage 
go 
use testMessage 

go 

CREATE TABLE [user] (
    userid int NOT NULL IDENTITY, 
    name nvarchar(200) NOT NULL, 
    PRIMARY KEY (userid) 
) 

go 

CREATE TABLE [message] (
    msg_id int NOT NULL IDENTITY, 
    userid int NOT NULL, 
    msgContent nvarchar(200) NOT NULL, 
    created datetime NOT NULL default getdate(), 
    PRIMARY KEY (msg_id) 
) 

go 

ALTER TABLE [message] 
    ADD FOREIGN KEY (userid) REFERENCES [user](userid) 
     ON DELETE CASCADE 
     ON UPDATE CASCADE 

go 

CREATE TABLE message_folder_type (
    message_folder_type_name varchar(40) NOT NULL, 
    [type] varchar(10) NOT NULL DEFAULT 'User', 
    PRIMARY KEY (message_folder_type_name) 
) 

go 

CREATE TABLE message_recipient (
    message_recipient int NOT NULL, 
    userid int NOT NULL, 
    message_folder_type_name varchar(40) NOT NULL, 
    PRIMARY KEY (message_recipient,userid) 
) 

go 

ALTER TABLE message_recipient 
    ADD FOREIGN KEY (message_folder_type_name) REFERENCES message_folder_type(message_folder_type_name) 
     ON DELETE CASCADE 
     ON UPDATE CASCADE 
ALTER TABLE message_recipient 
    ADD FOREIGN KEY (message_recipient) REFERENCES [message](msg_id) 
     ON DELETE CASCADE 
     ON UPDATE CASCADE 
ALTER TABLE message_recipient 
    ADD FOREIGN KEY (userid) REFERENCES [user](userid) 


INSERT INTO [user] VALUES ('Bob'); 
INSERT INTO [user] VALUES ('Harry'); 
INSERT INTO [user] VALUES ('Salley'); 
INSERT INTO [user] VALUES ('Jim'); 
INSERT INTO [user] VALUES ('Jake'); 
INSERT INTO [user] VALUES ('Randall'); 
INSERT INTO [user] VALUES ('Ashley'); 

INSERT INTO [message] VALUES ('4', 'this is a message', '2011-03-01 15:47:07'); 
INSERT INTO [message] VALUES ('2', 'this is a reply to message 1', '2011-03-02 15:47:28'); 
INSERT INTO [message] VALUES ('7', 'another cool message', '2011-03-02 15:48:15'); 
INSERT INTO [message] VALUES ('4', 'blah blah blah Sally', '2011-03-09 15:48:43'); 

INSERT INTO message_folder_type VALUES ('Deleted', 'System'); 
INSERT INTO message_folder_type VALUES ('Inbox', 'User'); 
INSERT INTO message_folder_type VALUES ('Sent', 'User'); 
INSERT INTO message_folder_type VALUES ('Trash', 'User'); 

INSERT INTO message_recipient VALUES ('1', '1', 'Inbox'); 
INSERT INTO message_recipient VALUES ('1', '2', 'Inbox'); 
INSERT INTO message_recipient VALUES ('2', '4', 'Inbox'); 
INSERT INTO message_recipient VALUES ('2', '5', 'Inbox'); 
INSERT INTO message_recipient VALUES ('3', '5', 'Inbox'); 
INSERT INTO message_recipient VALUES ('1', '4', 'Sent'); 
INSERT INTO message_recipient VALUES ('2', '2', 'Sent'); 
INSERT INTO message_recipient VALUES ('3', '7', 'Sent'); 
INSERT INTO message_recipient VALUES ('4', '4', 'Sent'); 
INSERT INTO message_recipient VALUES ('1', '3', 'Trash'); 
INSERT INTO message_recipient VALUES ('4', '3', 'Trash'); 


SELECT [message].msg_id, [message].msgContent 
    FROM message_recipient 
    INNER JOIN message ON [message].msg_id = message_recipient.message_recipient 
WHERE 
    message_recipient.userid = 4 
    AND message_recipient.message_folder_type_name != 'Deleted' 
ORDER BY message.created DESC 
fast action for sqlserver 
Problemi correlati