MySQL question for conversation app - mysql

I have an app that manages conversations between users on a website. It does one to one conversations as well as having multiple people in a single conversation.
Here is the layout for the mysql tables
conversations
conversations_meta
The conversations_meta table links users to the conversations by logging user_id and conversation_id. It also holds meta info about the conversation specific to each user in the conversation.
What I am having trouble with is detecting if a conversation with the same people already exist.
For example if a conversation between Eric Jason and bob exists but maybe it's old and the user forgot about it and then tries to create an addition conversation with the same users I would like to notify them of the conversation.
So the query should look in conversations_meta table and compare user_id and conversation_id to see if the same conversation exists already. Also I wouldn't want it to return conversations that include all the same users and additional users as well.
The main reason I posted this question on here is to get the fastest query possible to accomplish this task since there will be thousands of conversations.

What about this:
SELECT conversations_meta.conversations_id FROM conversations_meta
where (conversations_meta.user_id=1) or (conversations_meta.user_id=2)
group by conversations_id HAVING count(*) = 2
NOTE: this is a case for only 2 people in the conversation. Easily expanded to the case of 3 or or more.

Related

Is there a scalability issue in having a one-to-many relationship between participants and conversation?

I have a database design as shown in following entity-relationship diagram (ERD):
https://app.dbdesigner.net/designer/schema/0-social_media-00a3405c-0bcd-4809-9f8e-e86c1b8e5f33
I was wondering if I should have a one-to-many relationship between Participants and Conversation.
Issue: need many joins
The issue is that we need to make a join every time we want to get the id of the Participants of a Conversation to broadcast Messages.
Not only that, but we also need the content of the Messages, meaning we need to make two joins between three tables.
Questions
Is there a more scalable solution for this?
Is there any bottleneck issues?
Is there anything else wrong with the table aside that as an added bonus?
Scalable because:
If one conversation attracts more and more Users (in their role as participants), you simply have to add rows in the table Participants. Imagine the conversation has a members-list, it's called Participants.
If one User account was deleted, you simply have to search for all his records (associated conversations) in table Participants and delete them as well.
Both cases mean only a modification of Participants, whereas the conversation remains untouched.
Associative Entity
This membership or relationship of User to Conversation is bridged by a so-called associative relationship, associative table or associative entity. Means one User can attend (participate in) 0 or many Conversations, vice-versa one Conversation can have (at least) one (the creator) or many participating Users.
So the entity/table Participants acts like a bridge: connecting two sides/perspectives.
Broadcast Example
User A wants to broadcast a message to the channel/conversation 1. Now the system needs to determine all recipients. So look only within table Participants for the conversation 1 and find their attending Users A, B and C. All except the sender A should receive the broadcast: B and C.
There was no join involved. A simple query: SELECT user_id FROM participants WHERE conversation_id = 1 AND user_id <> 'A'. Given the Message and assuming that user_ids can be used directly as destination (email-address, phone-number, etc.), the system can immediately send the broadcast out.

MAX() Message Inbox Summary?

This question has been asked 1000 times, but I can't get it to work by modifying other peoples examples.
I have a messages table:
id
message
reciever_id
reciever_seen
sender_id
I want to create a mysql query that will show only the latest message sent for each conversation.
There can only be 1 conversation from user to user, and conversations cannot be deleted (for now)
The best answer will go to the responder who explains in detail how the query functions work together to give the results.

Social Network SQL statement for posts

I have been working on a Social Network to further my knowledge with PHP, however I have come to the point where I will be pulling posts from he database depending on who the user is "friends" with.
My database structure for friends is as follows:
USER_A | USER_B | CREATED_AT | IS_BLOCKED
And then for the posts:
USER | UPDATE | STATUS
So, I want to show posts selected from my post table if the user logged in is friends with the user who posted it.
So, basically, wondering if anyone has any suggestions. It won't be anymore complicated than that, not interested in getting friends of friends or anything like that. So, just wondering if someone could point me in the right direction with this one.
I read it would require JOINs and such, however I have never really stepped into that side of SQL so therefore would have no idea what I would be doing with it, so links to relevant questions and articles on that, if required, would be appreciated.
Thanks
(I am essentially looking for help with the SQL statement, not with the PHP.)
Update #1:
I have got the newsfeed working, now I need to be able to join a statement to get the users names to be displayed. My current status is on this: http://sqlfiddle.com/#!2/b07793/1/0
Before anyone goes crazy about storing passwords in plaintext, this is not a public system, it is purely for me to test, and hashing passwords for a non-public script that will only ever be used by me with fake passwords is hardly a security risk, it just makes debugging a pain.
Something like this should work :
SELECT * FROM posts
JOIN friends ON posts.user = friends.user_b
WHERE user_a = 'someuser'
In this statement we are JOINING to tables : posts and friends, based on the value of two column, we are putting in relation the column user of the post table with the column user_b of the friends table, in this way we will obtain a result set with only the value of the two table where the two columns in relation are equal ...
If I understood correctly the db schema you described, this will bring you all posts that have been written by a user that is friends with the logged in user.
SELECT * FROM posts WHERE posts.user IN (SELECT user_b FROM friendships WHERE user_a=$logged_in_user)
The query is pretty simple. You get all the rows from table posts that the creator of that post has a line in your friendships table as user_b while user_a is set to be the logged in user.
I'm assuming a few things, if they're not correct you'll have to modify this stuff but if I'm right, these operations won't need any JOINs:
$userSession variable contains the user who's logged in's ID.
$userToView variable contains the user who he's trying to view's ID.
Your database structure will only have one entry for the two users who are friends, so we have to check both combinations.
To determine if the user is a friend:
SELECT user_a, user_b FROM friends
WHERE (user_a = $userSession AND user_b = $userToView)
OR (user_a = $userToView AND user_b = $userSession)
LIMIT 1;
Then you'd use an if statement in PHP (it's usually better to keep business logic in the application, rather than in the database), if it's true return the posts.
$results = $mysqli->query($query)->fetch_row();
if($results) {
... return posts ...
} else {
echo 'Not friends';
}
That would be a query something like this:
SELECT * FROM posts
WHERE user = $userToView;
You will need to read up about mysqli (do not use mysql plugin, it's deprecated) and about SQL injection attacks and how to prevent them. It may sound like a hassle, but it's far less daunting to understand this stuff than to deal with the fallout if you don't.

Messaging system database schema

I'm trying to implement a messaging system in PHP and MySQL but I'm having some trouble deciding on how I should do the tables and queries.
What would be the best approach for a system that allows for multiple participants? I'm thinking I'd probably need 3 tables (aside from an users table).
Something like
Conversation
------------
id
Messages
--------
id
conversation_id
from_id
subject
message
from_timestamp
Participants
------------
conversation_id
user_id
last_read_timestamp
The way it is setup I'd have to check for read messages by the timestamp instead of ticking off each message. I'd also be able to add participants at any time.
What do you guys think?
Thanks in advance.
I don't see much to complain about :) I'd probably cache the last modification date on the conversations table so that a list of "unread" conversations can be displayed quickly. This date would be updated each time a message is posted on the conversation.
I would have put the subject field on the conversation table. Putting it on every single message looks redundant.
Also, I'd save the creation time and the author user id of the conversation in its table.

Database Design: private chat, group chat, and emails

The communication between Facebook users seem to be stored in one long "conversation." So, emails sent and private chat messages exchanged all seem to be part of one long ongoing conversation.
I think this implementation works well for users (at least it does for me). I assume the table design for this part could be implemented this way:
TABLE: message
- message_id
- timestamp
- from_user_id
- to_user_id
- message
What if I wanted to support group chat? Would I do something like this:
TABLE: message
- message_id
- timestamp
- from_user_id
- message
TABLE: message_recipient
- message_recipient_id
- message_id
- to_user_id
I think it'll work. However, I'm wondering if it would make sense to the user if I displayed every single things that user has ever messaged anyone in one long conversation. It probably wont. Imagine a conversation with Person A mixed with group conversation with Person A, B, C, D mixed with conversation with Person E and so on ....
Any suggestion on what would be a usable concept to implement?
I believe a message should be an entity, regardless of platform or sender/receiver, with id,message,timestamp fields, and a message relation table - like you suggested - with id,message_id,from_id,to_id.
Then, if you are showing a single user to user conversation, you can show every message between them.
For group chats, you should have a table with id,title,timestamp that holds the group chat main record, and another table that holds the users that are part of that group chat, with id,group_chat_id,user_id fields.
Just my opinion and how I would implement it.
Edit: Maybe it would make sense to have from_id on the message entity itself, as a message has to have a singular sender id.
You could also group messages by topics.
You add a topic table. You add a recipients table, tied to a topic. Messages will also be tied to a topic.
You can programmatically limit the topics between two users by looking which topic has those two users in its recipients.
You could also separate your messages by giving them a type attribute. For example, type 0 will be an inbox message, type 1 will be a chat message and so on.
If I wanted to have an arbitrary number of recipients in one topic, I would avoid the from_id/to_id combo.