Reputation: 566
I'm looking for some advice on how to design a database for an email-style application, specifically how to handle sending a message to multiple users, and displaying what messages were sent to what users.
This is what I have so far:
Messages (Primary Key is Id)
ReceivedMessages (Primary key is MessageId + RecipientId)
So for every message sent, there would be one row in Messages, with the data, and then one row for each recipient in ReceivedMessages.
But what if I want to view all the messages sent by a user, and who they were sent to? For each message, I'd need to find all the ReceivedMessages rows for that message, and join all of those with the user table, and then somehow concat all the names (something like this: Concatenate many rows into a single text string?). Might this cause scaling issues, or is it not really anything to worry about?
Any thoughts/suggestions? Thanks.
Upvotes: 0
Views: 2387
Reputation: 1
I am facing the same challenge of creating an email or messaging system for a website... You guys forget one thing... IsRead, IsDraft, IsFlagged, IsReply, IsTrash, etc... need to be in a separate table since the same message will be flagged, read or unread by two or more people!! So, we must have a Status table as shown below...
StatusID int
MessageID int
MemberID int
DateTime datetime
IPAddress varchar(65)
IsRead char(1)
IsDraft char(1)
IsFlagged char(1)
IsForwarded char(1)
IsReply char(1)
IsTrash char(1)
You will need at least three tables besides the member or user table:
mail
folders
status
attachment
log
If this is for an existing website... I would separate the mail system into a separate database if you expect this mail system to have a lot of activity.
Upvotes: 0
Reputation: 78413
Users change name and email, but not their login. Consider mimicking what happens in a unix-based mailbox (e.g. pine) instead:
received_messages (
user_id,
message_id,
message_date,
message_title,
message_content,
message_sender,
message_recipient,
message_is_read
)
and sent_messages
along the same lines, i.e. two "files" per user.
Or even merging the latter two with a sent/received flag.
Upvotes: 0
Reputation: 20456
all the messages sent by a user, and who they were sent to
You can do it as an aggregate query, something like:
SELECT u1.user_name, m.message, GROUP_CONCAT(DISTINCT u2.user_name)
FROM messages m JOIN users u1 ON (m.senderID=u1.user_id)
JOIN receivedmessages r ON (m.id=r.messageId)
JOIN users u2 ON (r.RecipientId=u2.user_id)
GROUP BY u1.user_name, m.message;
But because Recipients is essentially unlimited, you may run up against the string length limit on GROUP_CONCAT.
So it's likely better to do an unaggregated select and process the records for display in your application layer:
SELECT u1.user_name, m.message, DISTINCT u2.user_name
FROM messages m JOIN users u1 ON (m.senderID=u1.user_id)
JOIN receivedmessages r ON (m.id=r.messageId)
JOIN users u2 ON (r.RecipientId=u2.user_id)
ORDER BY u1.user_name, m.sent_date, u2.user_name;
Upvotes: 1
Reputation: 28016
I see no problem with your design, and would not anticipate and scalability issues with proper indexing on your tables (unless you are talking about massive scale, e.g. gmail, Yahoo mail, etc.).
As far as concatenating the recipient names, I would recommend you do this on the application side and not in SQL, or determine whether you need to do it at all (you might want to show a list and not a concatenated string).
Upvotes: 2