Get messages in a given trail - mysql

The following is a simplified table structure showing messages belonging to a single mail trail. i.e. the trail started with messageID 46 (where parentMessageID = 0). Message 47 is a reply to message 46. Message 89 is a reply to message 47.
tblMessages
messageID parentMessageID
-----------------------------
46 0
47 46
89 47
The table would obviously have thousands of message records.
How would you query the table to get all messages in a particular trail, e.g. the trail shown above?

Wouldn't it be better to store a conversation identifier?
The problem you're going to have is that you have no indication of the depth level, and so trying to loop over is almost impossible. It would be more logical to set the parentMessageID to the very root (i.e. where its parentMessageID == 0), and then order them by date.

Related

mySQL Messaging Between Two Users

I have a private messaging system that uses a mysql database.
Messages are passed between two users.
However, when any user deletes the conversation history, it should not be deleted in the other user.
I could create an Additional column called "deleted_users" and use LIKE when listing messages.
But I'm worried about performance and I need your help.
id
user_from
user_to
msg
1
82
85
test
2
85
82
test

Reading data from table using LIMIT while the order changes

Okay, let me explain.
You know how Facebook Messenger and Discord both have the last messaged friends list? It is a list of all of your friends order by whoever texted you last. Now, if you had over 100 people in that list, it would be better to send the list to the client in chunks of 10. Once the client reaches the bottom, it asks for the next 10. This can be done with the LIMIT offset, amount.
But now, the problem. The user might open the messenger, talk to someone for 10 minutes, and then scroll further down in the last messaged friends list. In this case, the table has changed before the user has retrieved the full list. The list in database is now in a different order because someone messaged them in the meanwhile and is now on top of the list, but the client already has the first chunk of the list, but this doesn't contain the people that texted them.
In case my explanation was not enough, here's a visual demonstration:
Visual demo
'Last messaged friends' list in database (ordered by latest timestamp):
Person 23
Person 77
Person 93
Person 99
Person 67
Person 85
User connects, asks for the first 3 entries.
Client now has (ordered by latest timestamp):
Person 23
Person 77
Person 93
'Person 99' messages that user. 'Person 99' is now on top of the list.
'Last messaged friends' list in database (ordered by latest timestamp):
Person 99
Person 23
Person 77
Person 93
Person 67
Person 85
User scrolls down. Client asks for the next 3 entries.
Client now has (ordered by latest timestamp):
Person 23
Person 77
Person 93
Person 93 (duplicate)
Person 67
Person 85
('Person 99' missing)
Is this something I could fix/implement with a more advanced SQL query?
If I can't, how could I implement this in other ways?
For information, I have a Socket.io (a.k.a more advanced WebSocket) connection between the server and the client, I can send whatever necessary information thru that.
It sounds like you want aggregation to avoid duplicates:
select person_id
from messages
group by person_id
order by max(timestamp) desc;
Thank you, Hector Vido, for the suggestion. (he made a comment right below my question, go upvote)
"Selecting messages by timestamp don't solve this? You keep the last timestamp and then ask by anoter 10 registries >= that timestamp"
Solution
I'll keep the oldest and newest timestamp in the client side.
If the client scrolls down, I will request 10 entries before the oldestTimestamp and then the new oldestTimestamp will be the oldest timestamp of the received entries.
Also after every 10 seconds, I could request for entries after the newestTimestamp and then the new newestTimestamp will be the newest timestamp of the received entries.

Saving chat message in MySQL DB, scheme design

I'm building a pretty simple chat app that allows both 1 on 1 message and chat rooms for groups of people. I'm planning to have one Message table to store all chat messages, each message will also keep the sender ID and receiver ID, in the case of messages sent in a chat room, we also keep the ID of that chat room. Below is the table:
Message Table
ID Message Sender Receiver Chatroom Timestamp
1 Hello, David 123 321 1495330074
2 Hi, Linda 321 123 1495930032
3 Hi everyone! 456 999 1495930132
4 What up? 321 123 1495930192
...
Then if I'm user 321, and I want to retrieve my conversation with user 123, I just need to SELECT * FROM Message WHERE Sender=123 or Receiver=123 or Sender=321 or Receiver=321 and Chatroom IS NULL
There is one issue with this design - a user can't delete a message that he doesn't want to see any more.
To solve that, I think I can have a separate table to store what messages a user received or sent, like below:
User Message Table
ID UserID MessageID
1 123 1
2 321 1
3 321 4
...
It seems a little redundant, but this way David can delete a message in his conversation with Linda, while Linda can still see full conversation history.
Is there better design of the tables? And is this good practice to throw all chat messages in one giant table? Should I add some index to make query faster?
You can use this query.
delete from Message
where sender = 123 and user = 321
But this will delete all the chat messages between this user and sender. To delete specific message you can use ID
delete from Message
where ID = 1

Reliable and accurate threading structure for emails?

I'm working on a email project. I would like to display email in threads just like gmail.
What is the best approach to display mails in thread?
I have checked jwz threading algorithm. But looks like that algorithm is written for projects that has no databases.That algorithm focuses on these three header keys. Message-ID, In-Reply-To and References
Can someone tell me what is the proper, efficient and most accurate way to achieve threading using mysql database.?
Do I have to use separate table for threads and references?
If possible give me some sample mysql queries. So I can understand better.
Thank you.
Any message board design eg wordpress etc should also works for email. I also come up with a design:
email.id user_id subject status folder created updated ...other info you'd save
1 123 Hello New Inbox Y-m-d.. Y-m-d.. ...
2 3456 World Replied Inbox ...
reply.id email_id reply_to_id user_id created email_txt ip ...
10 1 0 890 Y-m-d.. Hi ...
20 2 0 5678 ...
30 2 20 3456 ... Replyto 2
55 2 30 5678 .... Replyto 3
So in your email.folder.index page:
SELECT * FROM email WHERE user_id = 12345 ORDER BY updated desc LIMIT 50
And when you click one an email on index page, goto email details page:
SELECT * FROM reply WHERE email_id = 2 ORDER BY created, reply_to_id
The key magic is that the tree is built based on reply_to_id

mysql update duplicate records based on data from a associated table

Ok, I am going to attempt to ask this question again. My last post got closed cause it wasn't a more elaborate question so I will try to be more specific.
A user receives messages and the status is marked unread or read based on whether they clicked hat they've read the message or not.
Well there have been users that said they recieved duplicate messages. The problem is the record that keeps track of the message is in a second table. so the 2 tables look like this
subject_table
id user_id message_id created status
1 34 81 03/11/12 read
2 34 82 06/15/12 unread
3 34 83 06/16/12 unread
4 35 84 07/10/12 read
5 35 85 07/12/12 unread
6 35 86 07/14/12 unread
7 35 87 07/14/12 unread
8 24 88 08/09/12 read
message_table
id message
81 'welcome'
82 'welcome' //duplicate for user 34, associated table needs to be set to read
83 'welcome' //duplicate for user 34, this record needs to be set to read
84 'welcome'
85 'welcome'
86 'welcome'
87 'pretty cool' //not a duplicate for user 35
88 'welcome' // not a duplicate for user 24
what makes this question different from the first is there is a associated table here. I need to go through each table and only update tables that have duplicate messages. see record 87 in message_table? well there is no duplicate so that is ignored.
So my question is how do I update table 1 based on duplication with the associated table.
[EDIT]
When I mean duplicate, I mean all users with a associated message with the same message value.
so looking at the example. user_id 34 has 3 records. if we look up the message_id for each record, we will find the same message 'welcome' repeated 3 times. this is a duplicate record for user_id 34
The following is a fail
UPDATE subject_table
SET `status` = 'read'
WHERE
user_id IN (
SELECT
s.user_id
FROM
subject_table s
INNER JOIN messages m ON m.id = s.message_id
WHERE
m.message LIKE '%welcome%'
GROUP BY
s.user_id
HAVING
count(s.user_id) > 1);
What I am trying to do here is in my subquery, get the list of ids that have multiple duplicate records then update the associated record status to read.
But the issue I get with this is the following error
Error : You can't specify target table 'subject_table' for update in FROM clause
Assuming that for a message to be duplicate, all of user_id, message and created must be the same, the following statement should do it:
UPDATE subject_table, message_table
SET subject_table.status = <status>
WHERE subject_table.message_id = message_table.id
AND subject_table.user_id = <user-id>
AND message_table.message = <message>
AND subject_table.created = <created>
(where <user_id>, <message> and <created> are placeholders for actual values for the respective columns and <status> is the value for the new status)
This is called the multi-table UPDATE syntax and is described here: http://dev.mysql.com/doc/refman/5.6/en/update.html