How to properly store chats between two users [closed] - mysql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am currently working on a private chat between two users using NodeJS, AngularJS, MySQL and Socket.IO. I want to somehow save the chats so that you don't only see the new chat you are writing that gets transmitted via Socket.IO but also the messages you have written before your current sessions.
How do I properly store these previous chats on my server?

The usual way to do this is :
Table messages:
message_id PRIMARY KEY
sender_id FOREIGN KEY
recipient_id FOREIGN KEY
Index on (sender_id, recipient_id, message_id)
Index on (recipient_id, sender_id, message_id)
However, this structure has a problem: there is no easy way to efficiently sort the last N messages by "id DESC" because you'll have something in your WHERE like "WHERE sender_id=... OR recipient_id=..." and this will make the last two indexes (which are intended for fast sorting) kinda useless.
A smarter structure is thus:
Table chatrooms:
chatroom_id PRIMARY KEY
Table chatrooms_users
chatroom_id FOREIGN KEY
user_id FOREIGN KEY
Now, when two users (or more) want to start chatting together, you either create or reuse a chatroom from said table, and insert the relevant lines into chatroom_users to link the chatroom to its active members. This should be updated as users join/leave the chatroom.
If conversations only involve two users (and never more than two) then you can use a simpler structure:
Table conversations
conversation_id PK
first_user_id FOREIGN KEY
second_user_id FOREIGN KEY
Anyway. The whole idea is to give a unique identifier to a thread of conversations between our two users, or to a chatroom. Then, the messages table becomes a lot simpler:
Table messages:
message_id PK
chatroom_id (or conversation_id) FK
sender_id FK
Index on (chatroom_id, message_id)
In this case, note that the last index optimizes this:
SELECT * FROM messages WHERE chatroom_id=constant ORDER BY id DESC LIMIT 10
Thus, when the user opens the chat window with another user, you can find the conversation_id (or chatroom_id) easily, with an index lookup, and list the last messages quickly, also using an index lookup, and without any sort.
Old messages should be pruned and moved to an archive table, to keep the messages table small and cachable in RAM.

Related

Clean auto increment on primary key with multiple indexes

I have a table that holds various users by user_id with many other indexed columns of ids from third-party tools they use.
For example, table users
user_id | user_name | zendesk_id | mailchimp_id | todoist_id
We have crons configured to hit these third parties for a list of users so that our db has any new users inserted. In the event of a user_name change on the third party, we also want to update that information on our side to keep in sync.
user_id is a primary key with auto-increment.
all third party service columns (ex. zendesk_id) are unique and indexed.
Per mysql documentation, auto-increment will not work properly when other columns are indexed (see similar, but not duplicate question explaining this: ON DUPLICATE KEY + AUTO INCREMENT issue mysql )
Since mysql has this documented problem, my question is this:
How can I keep a reasonably clean auto-increment on user_id when I am pulling full user lists from these third parties to insert new users and update existing users?

Does it make sense to create a uniqueID for this MySQL table in a database? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I’m currently trying to design my table structures for a made up database. The database will have three separate tables and track the populations of cities for 10 years. After every year, population figures will be added for each city in the database. Here is how I’ve laid out my three tables so far:
Cities (city_id, city_name, city_abbrv)
Year (year_id, year)
Stats (year_id, city_id, population)
I’m worried about not having a unique identifier in my Stats table. With 10 cities, the year data will be the same for 10 entries. Once I enter multiple years of data, the city_id will be reused. In my research on this site I’ve read that having a unique ID for every table is not required but the book I’m using to learn database design (while brief) never mentions that this is okay. I would like to know the best way to design a database that receivers data entries for the same group of things on a daily/weekly/monthly/yearly schedule. Should I add in a unique_id column to my Stats table? Or would this be a wasted column? Thanks for the help!
First of all you need each of those tables to have the column id as primary key.
A primary key is used to uniquely identify a table row. A primary key cannot be NULL since NULL is not a value. So basically those columns will be unique yes.
Question: Why you need primary keys in your tables?
Answer:
If you are looking to select data from different tables you are opting for join so you need keys to use for that join.
If you want your
table to be clustered, you need some kind of a primary key.
Side Note: You may need to get familiar with indexing columns, see advantages of indexing.
Cities (id, city_name, city_abbrv) //with id as primary key
Year (id, year) //with id as primary key
Stats (id, year_id, city_id, population) //with id as primary key
//And year_id and city_id as foregin key connected by their respective ids
If you are still beginner with MYSQL see the W3school tutorial for SQL primary keys.

Foreign key links

I'm unsure how to link my tables:
Users(registration details of users),
Personal (personal details of users),
Academic (academic details of users),
Language (language details of users),
Thesis (Thesis details of users),
Referees (Referee details of users),
Addresses (Address details of users)
Should I have an 'id' field in each of the tables so I can join them all? Plus a primary key of of e.g. Academic_ID. Which would I set as auto inc?
Once the users registers, my system should link information from the users table to all other information they enter for the other tables.
I hope this makes sense
thanks
Add a field named "user_id" to your Users table. Then, in each table you wish to join to Users add a field with the same name.
This way, you could make a query like:
select * from Users, Personnal
where Users.user_id = Personnal.user_id
which would join your results the way you want. About your second question, yes you can/should add a unique autoincrement field like personnal_id and so on. Good practice and makes you record unique.
I tend to do an id field as the primary key (autoincrement), then you can do a unique key on lets say user_id (in each table) and then u can use user_id to link the tables.

data model and app logic question?

basically i have this problem i have a table of posts(in my mysql database)
Post{user_id, post, vote_up(int), vote_down(int)}
because users log in, then they get to vote, but i wanted to check if the user has already voted, so then i can not allow them to vote again, and obviously im going to be using user session to control this oppose to tracking ips etc.
so i was thinking do i have to create another table or is thier a better approach.
You will need another table e.g. called "votes":
Vote{user_id, post_id}
I assume, that your "Post" table has a primary key (e.g. "id") that you have not shown in your question above? Then "post_id" should be a foreign key to Post#id.
/Carsten
You'll definately need another table, and some primary and foreign keys would help too:
Post{post_id(int), user_id(varchar), post(clob)}
Votes{vote_id(int), post_id, user_id, up_down(char)}
Your vote_up and vote_down column values are removed and are now calculated with queries:
-- vote_up
select count(*) from votes where post_id = n and up_down = '+';
-- vote_down
select count(*) from votes where post_id = n and up_down = '-';
There should be a unique index on votes(post_id, user_id) to prevent multiple votes by the same user on the same post.
The primary key vote_id does not have to be defined, but each table should have a primary key and if you don't want to use a surrogate key, then you can define the PK using the same columns as above and this will serve as the unique index too, so ot does not have to be defined.

How to store "wishlist" in database? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I am thinking of creating a "wishlist". Each user will be able to purchase wishes in a shop. How do I store the wishlist? I am thinking of creating an user table and a wishlist table.
The structure of user table:
Columns: id, username, password etc
Columns: id, wish, price, quantity etc
user id is the primary key for user table and its a foreign key in wishlist table. However, when I come to think of it, my wishlist table will have duplicate items for each user, won't it?
Is there a better way to store the wishlist things?
I am using mysql. Thanks
You should also have another table to store the purchases:
Purchases
Id
UserId
WishId
PurchaseDate
Users
Id
Name
Password
Wishes
Id
Wish
Price
Quantity
Every time a user purchases a wish, you create a record in the Purchases table, and decrement the Quantity count for that wish.
It is a 1 to n relationship.
Asuming you have a User table with a user_id as primary key then
create a table Wish which has user_id as foreign key.
Add the attributes you want to this second table and violá.
Luis
You should have another table for wishes (wish id, price, description etc), and you should have a joining table (user id, wish id, quantity, quoted price etc). This table will allow you to have a many-to-many relationship between users and wishes.
(Further to my comment... see? You have two different suggestions already. Ultimately you have to decide what is best, and ideally your business/project requirements should guide you.)
EDIT: make that three different suggestions
You essentially need to know just a few things to add information to a wishlist. Here's how I have it in one of my client projects:
Wishlist
wishlist_id
user_id
product_id
created_date_time
It would make sense to have wishlists only for authenticated users, so ensure that you are taking care of that.