I am developing a community site for high school students. I am trying to implement a like and unlike system using PHP. Heres what I have got :
A table named likes in MySQL with 3 columns namely app_id VARCHAR(32), user VARCHAR(12), dormant VARCHAR(6).
UNIQUE(app_id,user)
When a person likes a page on my site, a row is either inserted or updated in the likes table with dormant = false.
When a person unlikes a page, the row present is again updated with dormant = true. This is an alternative to deleting the row as it is a bit intensive for a speedy work of likes and unlikes.
I want to know, if I should go for deleting the row instead of updating it, when someone unlikes the page.
Dont Delete the row. Every data you can gather its a valuable data point.
I would say you should create a new record for every unlike also.
These data will be usefull to you in the future to figure out user behaviour.
Some ppl might like smth now and then unlike it , then like it again and so on.
Maybe in the future u would like to see why so many people who liked an item suddely unliked it then liked it again.
So i say gather as much data as you can.
Sounds like premature optimization. Don't do that.
Design your application as you want to use it /as it should work. When it gets busy, find out the bottlenecks and fix them.
If you want to design your application for scalability to the millions, consider using a different database engine / programming platform altogether.
Looks like you haven't record the number of user liked or unliked the pages. In this case, LIKES should be a many table and there should be another table called APPS (or any name you wish) to store pages:
**USER**
+---------+-------+-----+
| user_id | name | ....|
+---------+-------+-----+
| 1 | ... | ... |
+---------+-------+-----+
| 2 | ... | ... |
+---------+-------+-----+
**APPS**
+---------+-------+-----+
| app_id | name | ....|
+---------+-------+-----+
| 1 | ... | ... |
+---------+-------+-----+
| 2 | ... | ... |
+---------+-------+-----+
**LIKES**
+---------+-------+----------+----------+
| like_id |user_id| app_id | is_liked |
+---------+-------+----------+----------+
| 1 | 1 | 2 | 1 |
+---------+-------+----------+----------+
| 2 | 1 | 3 | 0 |
+---------+-------+----------+----------+
Where you can toggle if the user click like( is_liked = 1) or unlike( is_liked = 0) the page
Related
I have created a privilege system for my application which allows/disallows access to specific pages based on user input.
The table looks something like this:
page_id | client_id | sys_group_no | name | friendly_name | viewable |
1 | 4 | 1 | home | Home | true |
2 | 4 | 1 | admin| Admin Home | false |
So if the user in client_id 4 is of group 1 they are NOT allowed to view 'Admin Home' it isn't actually quite this simple but for the sake of this question we can pretend.
The problem is as maintenance goes on this table get out of date quickly, and when you have a few thousand rows, constantly checking the table against the actual page names (using scandir() and array_diff()) will be expensive. Is there a different paradigm for checking this kind of integrity other than direct comparison? - For instance would hashing my $page_array and comparing it be a better approach?
I am attempting at making a site that has a polling section in it. The users need to be able to take previous polls if they have not voted in them yet. So for each poll they take, it adds a note into the cell.
The table looks something like this:
userid | poll1 | poll2 | poll3 | poll4 /
---------+--------+--------+-------+--------/
001 | Y | Y | | /
---------+--------+--------+-------+--------/
002 | Y | | Y | /
--------------------------------------------/
So now, the code would have to select poll 3 and 4 for user 001, and present that to the user on the page. I have been trying a couple different approaches to this but can't seem to find the right code.
I have looked for something for help online and haven't found anything that addresses this issue.
Users
id | name
---+-------
1 | tyrion
2 | cersei
Polls
id | name
---+-------
1 | first poll
2 | second poll
UserPolls
user_id | poll_id
--------+-------
1 | 1
1 | 2
2 | 2
In the above table structure, you have the two main object tables, and one relational table, called UserPolls. This will scale pretty well, for any number of polls you want.
Then, if you want to know which polls were taken by a given user, you can do:
SELECT poll_id FROM UserPolls WHERE user_id = 1
Or if you want the opposite. Polls not taken by a given user:
SELECT id FROM Polls WHERE Polls.id NOT IN (SELECT poll_id FROM UserPolls WHERE user_id = 1)
Note: this is not tested code, but you get the general idea on how to go about designing and normalizing your tables.
For the sake of simplicity in explaining this, imagine a room full of people talking to each other. Every statement made by one person to another would be a record in this table, and all of these records have a unique ID assigned through auto-increment.
However, not everyone in this room is talking to everyone else. There's multiple conversations going on.
These conversations need to be unique amongst themselves. This would prevent a duplicate conversation ID being started, and the site collecting all statements which don't belong to that person.
Or, in graphical representation:
----------------------------------------------
| MessageID | ConvoID | Sender | Recipients | etc...
----------------------------------------------
| 1 | 1 | A | B |
----------------------------------------------
| 2 | 1 | B | A |
----------------------------------------------
| 3 | 2 | C | D |
----------------------------------------------
| 4 | 1 | A | B |
----------------------------------------------
| 5 | 2 | D | C |
----------------------------------------------
| 6 | 1 | B | E |
----------------------------------------------
| 7 | 3 | E | F |
----------------------------------------------
You can actually see the conversations that are taking place here... A talked to B (ID 1), who replied back (ID 2) at around the same time C started a new conversation (CID 2) with D (ID 3).
A finally gets back to B about something (ID 4) and D eventually response to C's earlier inquiry (ID 5). B then talks to E about the same thing he was talking with A about (CID 1) before E turns right around and connects with F to start a completely new conversation.
If this has read like the steps which occur prior to the immediate termination of an employee, it wasn't intended that way, but you're not alone.
So you can see that every DB entry has a unique ID (MessageID), but these messages need to be easily collated together.
The solution I'm seeking is something that allows the DB to create a new and unique "ConvoID". This is why we can't auto-increment, or why we can't force uniqueness on the data set. Duplicates must occur, by nature of what this column is doing, but auto-increment would do, perhaps, the exact opposite of what it is i'm seeking for.
Any help that could point me in the right direction would be significantly appreciated.
Thanks!
You could normalize the design by adding a Conversations table. The table would have its own auto-incrementing column. Whenever a new conversation is started, you add a row to Conversations, and use its identifier as ConvoID.
Both users and pages on my website have IDs. When a user goes on a certain page, their userID and the pageID will be written to a MySQL table as such:
userID | pageID
3 | 1
2 | 1
3 | 2
etc...
In this table, called user_pages, I would end up with a bunch of raw data that can be turned into a recommendation engine. What I mean by recommendation engine - I want to analyze historical data, and be able to predict, based on a set of viewed pages, the next pages that a user may like. Let's say there is a strong correlation between visiting page with ID 3 after going to pages with IDs 4, 9, 15. If a user goes on pages 4, 9, and 15, then the engine should recommend page 3.
I think I have all of the data input code necessary for creating this. How would I write something that analyzes the data for correlation of pages (i.e. almost everyone who visited page 5 visited page 1 also), and somehow use that to predict in the future the pages that a user may end up liking?
Recommendation systems are a big part of A.I research. I believe you are interested in a collection of algorithms called collaborative filtering. Since the netflix prize in 2007 this field has developed greatly. I would recommend going here and having a read. It explains the basic concepts of recommender systems in a succinct and clear way and also provides a link to Java source code for an approach to the Netflix project, MemReader. You could examine this source code and extrapolate the basic algorithms for building a recommendation engine.
Alternatively if you want a more mathematical explanation of the algorithms employed go here.
It shouldn't take too long to implement at all.
This post posed a similar question: Advanced MySQL: Find correlations between poll responses
I think you would be able to generate a similar response if your primary data table had one additional field in it, specifically the id of the page the used last visited or visited immediately following.
Something like this:
+------+----------+--------------+----------+
| id | page_id | next_page_id | user_id |
+------+----------+--------------+----------+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 2 |
| 3 | 1 | 2 | 3 |
| 4 | 1 | 2 | 4 |
| 5 | 2 | 3 | 1 |
| 6 | 2 | 3 | 2 |
| 7 | 2 | 3 | 3 |
| 8 | 2 | 4 | 4 |
| 9 | 3 | 5 | 1 |
+------+----------+--------------+----------+
Then you should be able to use a modified version of one of the SQL queries suggested there to generate a list of high-correlation recommendations between the current page and the next page.
I want to create something like reddit where they have comments, then replies to the comment, then reply to the reply.
What type of database structure do they use so:
1. they keep track of all the comments to a posting
2. a reply to a comment
3. a reply to a reply
All I have right are is just a posting and a bunch of comments relating to it like..
POSTING TABLE
posting_id | title | author
COMMENTS TABLE
comment_id | posting_id | comment
REPLIES TABLE
????
How do I relate the comments to the replies?
What type of css do they use to give replies that indented space?
EDIT:
Thanks for the answers! Now my only question how do I indent the replies?
Such as..
you like food
yes I love italian
Yes i do like it too
chinese is best
You can add another column to your comments table specifying parent_comment_id where you populate it with the ID of the comment (or reply) the user is replying to. In the case where the comment is a direct reply to the post (not a reply to a comment) this column would be null.
To show replies inside replies, you'll have to do a recursive call to keep on generating the sub replies.
Something like
function get_comments($comment_id) {
print '<div class="comment_body">';
// print comment body or something?
if (comment_has_reply($comment_id)) {
foreach(comment_comments($comment_id) as $comment) {
get_comments($comment->id);
}
}
print '</div>';
}
To indent comments however, use css.
<style type="text/css">
.comment_body {
margin-left:10px;
}
</style>
This way sub replies are indented more than the parent, and their subs are indented even more, and so on.
I would do that by making a cross reference table.
Example:
Table: Posts
Columns: pstkey | userid | postMessage | etc...
pstkey is the key for the post body. userid is the person who created the post. postMessage is the actual post entry.
Table: Comments
Columns: comkey | pstkey | userid | commentMessage | etc...
comkey is the key for the comment made. referenced to the post using the pstkey. userid is the person who made the comment. and then commentMessage is the text body of the actual comment.
Table: xref_postComm
Columns: xrefkey | pstkey | comkey | comkey2 |
Now for the fun part. ALL posts go into post table. ALL comments go into comment table. The relationships are all defined in the Cross Reference Table.
I do all of my programming this way. I was privileged to work with one of the worlds bests database engineers who was retired and he taught me a few tricks.
How to use the Cross Reference table:
xrefkey | pstkey | comkey | comkey2
All that you look for is the population of a given field.
xref (Auto Incremented)
pstkey (Contains the pstkey for the post)
comkey (Contains the comkey for the comment post)
comkey2 (Contains the comkey for the comment post)
(but only populate comkey2 if comkey already has a value)
and of course you populate comkey2 with the key of the comment.
SEE, no reason for a 3rd tabel!
With this method you can add as many relationships as you want.
Now or in the future!
comkey2 is your reply to a reply. Where which this single row contains.... the key of the post, the key of the comment, and the key of the reply to the reply comment. All done by population of xref.
EXAMPLE:
PAGES.... Page table
POSTS
pstkey | pageid | user| Post
-------------------------------------
| 1 | 1 | 45 | Went to the store the....|
| 2 | 2 | 18 | Saw an apple on tv.....
COMMENTS
comkey | pstkey | user | Comment
-----------------------------------------------
| 1 | 1 | 9 | Wanted to say thanks...
| 2 | 1 | 7 | Cool I like tha.....
| 3 | 2 | 3 | Great seeing ya....
| 4 | 2 | 6 | Had a great....
| 5 | 2 | 2 | Don't sweat it man...
xref_PostCom
xrefkey | pageid | pstkey | comkey | comkey2 |
----------------------------------------------
| 1 | 1 | 1 | NULL | NULL | Post1 on Page1
| 2 | 1 | 1 | 1 | NULL | Comment1 under Post1
| 3 | 1 | 1 | 2 | NULL | Comment2 under Post1
| 4 | 2 | 2 | NULL | NULL | Post2 on Page2
| 5 | 2 | 2 | 3 | NULL | Comment3 under Post2 on Page2
| 6 | 2 | 2 | 4 | NULL | Comment4 under Post2 on Page2 (a second Comment)
| 7 | 2 | 2 | 4 | 5 | Explained below....
Comment key 5 is matched with comment key 4....under post2 on Page 2
If you know anything about join, left join, right join, inner/outer join creating SELECT's to get the data arrays using these relationships, your job becomes a whole lot easier.
I believe the engineer's call this basically "the data map" of defined relationships. The trick is now how you access them using these relationships. It seams hard at first, but know what I know it, I refuse to do it any other way.
What happens in the end is you end up writing 1 script that says, ok, go do uhh, everything and come back. You will end up with 1 function call that asks for page 1. It returns with page1, post 1, comment1&2&3 and the replies to the reply in 1 array. echo to output and done.
UPDATE FOR COMMENT
I said the same exact thing the first time it was shown to me. As a matter of fact it really was making me mad that the database programmer was forcing me to do it this way. But now I get it. The advantages are so many.
Advantage 1) 1 query can be written to pull it all out in 1 shot.
2) Answers in multiple queries can populate arrays in a structure that when printing the page a loop in a loop can display the page.
3) Upgrading your software that uses it can support any possible design change you can ever think of. Flawless expandability.
The guy who taught it to me was the hired gun who redesigned sears and jcpenny databases. Back when they has 9 books going to the same house because of duplicate records issues.
Cross reference tables prevent a lot of issues in design.
The heart to this theory is, a column can not only contain data but serve as a true or false statement at the same time. That in it's self saves space. Why search 20 tables when you can search one? 1 indexed cross reference table can tell you everything you need to know about the other 20 tables, it contents, what you need, what you don't need, and do you even need to open the other table at all.
IN SHORT:
1 Cross reference containing nothing but INT(2/11) that tells you everything thing you need to know before you ever open another table, not only contains flawless expandability but lighting speed results. Not to mention little possibility of duplicate records. To you and me duplicate records may not be an issue. But to Sears with 4 billion records at $11 a book, mistakes add up.
Add another field to your comments table which "reply_to" or some such, and store the id of the comment which it is in reply to there.
you could make the comments table generic like so :
COMMENTS TABLE
comment_id | posting_type | posting_id | comment
where posting_type is some sort of discriminator, eg a string 'POST' or 'COMMENT', or an integer for more efficiency (1 = POST, 2 = COMMENT, etc).
edit : admittedly this is more complicated but it means you can use the same comment table for comments on anything, not just posts and other comments.
You don't need the replies table. As others already correctly have pointed out, recursion is the way to go with an RDBMS. You could always consider using a nosql style DBMS, to avoid having to deal with recursion.