I want to develop a social networking site, where users can make friends with other users, and I have the following example table:
Table Name : Friends
id | friends
id will contain the id of the user and friends will contain the ids of the user's friends in one row. The id column will be unique and primary key.
My Question
I would like to know if I can store the list of friends as a serialized array as that would limit the friend connections to only 1 row per user as against other methods described in here, which is have friends table, and insert user and friends id in each row.
During retrieval, I would unserialize the row and put it in an array.
You can do that but you'll then have to always keep it updated and there is no way to join on that information or search it accurately within a mysql query.
With an app like this you WILL need that data to be available.
If you're not comfortable with the SQL required to join the tables in the proper way just ask for help with the point of confusion / frustration =)
It can be done, but there is no advantage to it. It will be difficult to do aggregate functions, for example summing or finding the newest friend will be almost impossible. Doing joins will be impossible, without unserialising through code and making new queries. Also, you need to change the structure a bit:
Table Friends
ID | User_ID | Friend_ID
1 4 5
2 4 6
ID would be an auto-increment primary key, user id is the id of the user and friend id is the id of the friend
You shouldn't concat data (foreign id's) into an single field in an relational database. You won't be able to join/select any data. Instead use:
friends
userId, friendId
This would totally break the idea of a relational database.
You could also have a single table - person and storing on the first position the id of the person and the friends serialized after that.
The idea is that you can not make simple queries on those "database structures" like counting the number of friends, regardless to say common friends or other simple operations.
Anyway, I would recommend you to take a look at some Graph Databases and consider unsing one for your social graph
Related
I have a MySQL database that stores user emails and news articles that my service provides. I want users to be able to save/bookmark articles they would like to read later.
My plan for accomplishing this was to have a column, in the table where I store the users' emails, that holds comma-delineated strings of unique IDs, where the unique IDs are values assigned to each article as they are added into the database. These articles are stored in a separate table and I use UUID_SHORT() to generate the unique IDs of type BIGINT.
For example, let's say in the table where I store my articles, I have
ArticleID OtherColumn
4419350002044764160 other stuff
4419351050184556544 other stuff
In the table where I store user data, I would have
UserEmail ArticlesSaved OtherColumn
examlple1#email.com 4419350002044764160,4419351050184556544,... other stuff
examlple2#email.com 4419350002044764160,4419351050184556544,... other stuff
to indicate the first two users have saved the articles with IDs 4419350002044764160 and 4419351050184556544.
Is this a proper way to store something like this on a database? If there is a better method, could someone explain it please?
One other option I was thinking of was having a separate table for each user where I can store the IDs of the articles they saved into a column, though the answer for this post that this is not very efficient: Database efficiency - table per user vs. table of users
I would suggest one table for the user and one table his/her bookmarked articles.
USERs
id - int autoincrement
user_email - varchar50
PREFERENCES
id int autoincrement
article_index (datatype that you find accurate according to your structure)
id_user (integer)
This way it will be easy for a user to bookmark and unbookmark an article. Connecting the two tables are done with id in users and id_user in preferences. Make sure that each row in the preferences/bookmarks is one article (don't do anything comma seperated). Doing it this way will save you much time/complications - I promise!
A typical query to fetch a user's bookmarked pages would look something like this.
SELECT u.id,p.article_index,p.id_user FROM users u
LEFT JOIN preferences ON u.id=p.id_user
WHERE u.id='1' //user id goes here, make sure it's an int.. apply appropriate security to your queries.
"Proper" is a squirrely word, but the approach you suggest is pretty flawed. The resulting database no longer satisfies even first normal form, and that predicts practical problems even if you don't immediately see them. Some of the problems you would be likely to encounter are
the number of articles each user can "save" will be limited by the data type of the ArticlesSaved column;
you will have issues around duplicate "saved" article IDs; and
queries about which articles are saved will be more difficult to formulate and will probably run slower; in part because
you cannot meaningfully index the the ArticlesSaved column.
The usual way to model a many-to-many relationship (such as between users and articles) is via a separate table. In this case, such a table would have one row for each (user, saved article) pair.
Saving data in CSV format in a database field is (almost) never a good idea. You should have 3 tables :
1 table describing users with everything concerning directly the user
1 table describing articles with data about it
1 table with 2 columns "userid" and "articleid" linking both. If a user bookmarks 10 articles, this table will have 10 records with a different aticleid each time.
I've just started exploring SQL databases, but I've run into an issue with how I store 'compound' structures in an existing table (if that's even the right way to go about it). For example, let's say that I have a database table with rows of users, where each user has a Unique ID, a hashed password, an email address, a phone number, etc.
Simple enough. But, then I want to allow each user to create and store an array of posts. Each post would have a post id, content, date, and various other metadata. If this was C++, I would probably have an array/vector of Posts as a member of the User class, and than I'd store an array/vector of User objects somewhere. Is it possible to store a table within a table in SQL, so that each user has access to their own individual table of posts?
Or, would it be better to create two separate tables (a users table, and a posts table), using some common element (like user ID or user name) to retrieve user-specific data from the posts table, and vice-versa?
I'm trying to understand how to implement a complex database that might be able to manage a large number of users, with user-specific sets of data like posts, messages, etc. So what might be a good approach to take going forward?
As you already mentioned, in relational data model, you can define two tables like below:
table 1 : Users
user_id user_name
----------- ------------------
1 'Tom'
2 'John'
table 2 : Posts
post_id user_id content post_date
-------- ---------- ------------------- ---------------------
1 1 'Hello, I am Tom.' 2014-04-02 14:14
2 1 'good bye' 2014-04-02 20:10
3 2 'I am John' 2014-04-02 22:22
You can read an introductory article here:
Relational_model:
http://en.wikipedia.org/wiki/Relational_model
Hope this helps.
You don't store table within table. You can store data in multiple tables and assign primary key for one table and foreign key for another table.
Read about Primary key, Foreign key and Relational Model.
Once your these concepts are cleared read about Database Normalization
You don't store tables within tables. As your third paragraph suggests, the strategy is to use some common key to "relate" table rows to each other.
The "unique ID" you describe is usually called a "primary key". You might have a table of users with a primary key that auto-increments each time you add a record. A function would be available to you so that after inserting, you could determine what the primary key is of the record you just added, so that you can add records to other tables that refer to the primary key of the users table.
You should probably read about Database normalization ant the relational model, specifically about the differences between Normal Forms.
With regard to selection of a field to relate posts to users, I suggest you don't use the username, and instead use some internal reference that isn't visible to the users. While your application might not allow it now, if you wanted to offer users the opportunity to change their username, tying internal database structure to something based on user input would only cause problems in the future.
I am storing user ID values in a table field separated by a | (user_id1|user_id2|user_id3|user_id17).
A user ID will be added and removed from this field at certain points.
How can I check if the current users ID exists in the field or not using a query?
And it of course needs to be an exact match. Can't look for user_id1 and find user_id17.
I know I could use a SELECT query, explode the field, then use in_array but if there's a way to do it using a query it'd be better.
I guess I'll explain what I am doing: I made a forum for a small private website (7 users), but coding it for larger scale.
My table structure is pretty good: forum_categories, forum_topics, forum_posts. Using foreign keys between the tables for delete and update queries.
What I am seeking help on is to mark Topics as unread for each user. I could create a new table with topic_id & user_id, each one being a new row but that wouldn't be good with alot of users & topics.
If somebody has a better solution I am all for it. Or can prove to me that 1 row per user_id is the best way then I'll be more than willing to do that.
I think you want to track read messages, not the other way around. If you tracked unread messages, every time you add a user you'll have to add that user to every topics "unread list".
I looked into SMF like my comment suggested. They are using a separate table to track read messages.
A simple table that holds user_id and topic_id are you are need. When a user reads a topic, make sure there is a row in the table for that user.
Another reason to use a separate table. It's going to be faster to query against 2 int values in the database than to use LIKE % statements.
I am working on creating a favorites section on my website where users can simply store certain items in their favorites section for easy access. Each of the items are already well-defined and have multiple attributes. So my question is lets say I had 10,000 users and I would like to implement a 'favorites' system, what would be the best way to keep track of what favorite items have been added by each user?
I was thinking implementing this the following way: link each favorited item id to a username and then run a query for if the user with a particular username is logged in than retrieve all the favorited items by that username.
I appreciate any help with figuring out of a good way to do this. My goal is to store in a way that is later easy to retrieve and use the data and minimize redundant information.
It's pretty easy, you need to create a new table with 3 fields:
id
favoriteID
userID
Every time a user adds a new favourite, it adds a new record to this table, storing both the ID of the favorite, and the ID of the user. There is no redundant information and it's easy to retrieve the details of either the favorite or the user by implementing a join query. This is what relational databases are for.
Within an RDBMS you would probably have a many to many table with the user id and article id. You do not need an independent id column:
create table favourites (user_id int, article_id int);
These of course reference your user table and articles table. (Or whatever you have in place of articles.)
You would then need to retrieve all rows for a single user when wanting to show that user's favourites. You might also want to make a combined UNIQUE index on the columns to prevent duplicates.
You may have faster response with something like cassandra where you can simply retrieve based on the key of the user_id and get all their favourites in one easy spot. But then you're dealing with mutilple systems.
I've heard, but haven't had a chance to look into, that MySQL can now support a Key-Value system similar to Cassandra and that may be your best bet.
I wondered how a table should be structured when there is going to be more than one value for a certain field. For example, If I have a user who has 10 friends should there be a table that has 10 rows with the user's name and a different friend on each row or should there be one row with the user's name and all the friends put into one? Thanks, the answers will help a lot.
You should make a many-to-many table that links the foreign keys together of two people who are friends. So if Person is the entity you are using, you wouldn't want to constrain the structure by introducing limitations such as 10 friends into a single row.
Fundamentally, what you're trying to do is normalize your data. You should read up a bit on Database Normalization