I don't even know what questions I should ask. Well, I want to create a thumbs up for my comments, but not sure how or what's the best way. Do I just create a new field for thumbs up?
If you need to keep track of who's voted on what, you should perhaps make a Votes table:
vote_id: Primary key.
user_id: The id of the user who made this vote. [Foreign key to Users table.]
comment_id: The id of the comment that was voted on. [Foreign key to Comments table.]
vote: The vote that was cast (perhaps +1 or -1 if you only have a trivial thumbs up/down system).
date: When the vote was cast.
A comment's score is now just the sum of all the vote columns which have that comment_id.
Note that unlike simply adding an integer score column to your Comments table, this has the advantage of telling you the level of controversy a comment is experiencing. Without knowing how many votes were cast, two comments with a net score of zero could either be experiencing a lot of controversy (people are equally split about the merit of the comment, so the total score hovers around 0), or none at all (nobody cares enough to cast a vote).
Just storing an int for the number of times a comment has been voted up would be subject to abuse. You probably also want to associate each vote with the user who cast it, that way you can prevent people from repeatedly voting for the same comment.
For this to work, I think you'll need a separate table for votes. Each record in that table should have the comment id and the user id of the person who cast the vote.
It depends on what you want to do with this. Why not just put an int column on your comments table, storing the total number of thumbs up / down for the comment?
Creating a separate table, as Bill and John have suggested, would probably be the best approach. But you might still want to add a votes column to the comments table for performance reasons. This way, you won't need to access the votes table when you only want to display the vote count for a comment. I believe this is how votes work on SO.
Create 2 fields in your comment table, vote_up and vote_down, and increase their counters accordingly upon user's vote, this way you can display comment score as sum of these values or as a percentage, in the later case you could add third field vote_score which stores percentage score if you ever wanted to be able to sort by score.
Then create votes table to prevent users voting twice the same comment, ever or in given time span, if so just set cron job to run once a day and delete entries older than time()-( 86400 * DAYS_TO_KEEP_VOTE )
comment_id
user_id
vote_time
Good luck.
Related
I need to display the number of comments a user has post. I can think about two different ways of doing it, and I would like to know which one is better.
METHOD ONE: Each time I need to display the number of comments, query the comments table to select all comments with user_id x, and count the number of results.
METHOD TWO: Add a new column to the user table to store the number of comments a particular user has post. This value will be updated each time the user enters a new comment. This way every time I need to show the number of comments, I just need to query this value in the datbase.
I think the second method is more efficient, but I would like to know other opinions.
Any comment will be appreciated.
Thanks in advance,
Sonia
Well it depends. I suppose you use SQL. Counting is pretty fast of you have correct indexes (eg. SELECT COUNT(1) FROM articles WHERE user_id = ?). If this would be bottleneck than I would consider caching of these results.
At scale, option #2 is the only one that is viable. Counts may eventually be skewed some and you may need to rebuild the stats but this is a relatively low cost compared to trying to count the number of rows matching a secondary index.
I have a website where users can rate comments that are left on pages. Each comment has a unique ID (E.g. 402934) If I want users to be able to thumb-up/thumb-down said comments I can see how I would make a simple counter code to keep track of the number of thumb-ups vs thumb-downs but how can I make sure that each user only ranks said comment once. I was going to make a database with each comment number as a row and in that row having an array of all the users that have ranked it thumbs up and all the users that have ranked it thumbs down but I had a feeling that wasn't the best way. My next thought was to have a table for each user and then having an array showing all the comments said user has ranked. It would probably run faster this way (e.g. checking from a user's 150 rankings verse a comment's 6050 rankings but I still feel like there is a better way... any ideas?
Create a new table with user_id, comment_id and vote TINYINT(1).
A value of 1 in vote is a thumbs up, A value of 0 in vote is a thumbs down.
Have a UNIQUE KEY constraint on (comment_id, user_id).
If you follow the above it will be easy to check whether a user has cast a vote on a specific comment, if you'd like to be able to quickly (as in fast execution) see all the comments a user has made you should also add an INDEX to user_id.
When a user votes you could use REPLACE INTO to user_comment_thumbs, such as the below:
REPLACE INTO `user_comment_thumbs` (user_id,comment_id,vote)
VALUES (#user_id, #comment_id, #vote);
If the user has already made a vote the entry in the table will be updated, otherwise a new row will be inserted.
i dealing with a case that i allow every topic to have only 100 lasts comments
in case a topic have already 100 comments , and a new comment i coming i want to delete the very first comment in the 100 comments chain and add the new one , here is an example :
1,2,3 .... 99 , 100
2,3,4 ....100 , 101
as you can see the very first comment that was far behind the others got deleted and the new one got in the 100 comments chain
here starts the problem , if i have in my case forum , and this forum have hundreds thousands of topics , it can reach millions of comments , which means if i check how many comments there are with every new incoming comment it will cause slowing the site with every comment adding , how can i minimize the data base query's ? is there any system / known ways to facing that kind of things?
Why would you delete old comments? If you want to show last 100 comments, then just SELECT id, thread_id, user_id, comment_body from COMMENTS where thread_id = #thread_id LIMIT 100. Also be sure to have indexing on foreign column so that it gets queried fast and query only columns you need.
And no, if you are going to be wise with queries, apply indexing where needed then you don't need to worry about each comment slowing down the database. Will you have millions of millions of comments? If so, you can think about partitioning the database say every 1000000* threads based on thread_id.
You may be interested in this question: Database architecture for millions of new rows per day
* For anyone who reads: Don't assume this number as some advice or suggestion out of experience. Never say: "someone on SO mentioned this number x, so..." I have no experience or benchmarks to say that it would be good to do it at this number. I'm only creating my first partition myself. Evaluate yourself what is good for you.
What's your database structure for this stuff? Presumably you have a "posts" table, and a "comments" table, which links back to the posts table. Assuming decent design, the comments will have an auto_increment primary key, so your logic would be:
1. insert new comment
2. count the comments attached to the post. If it's > 100, then
3. find min(comments.id) and delete that ID.
I'm having some trouble approaching a +1/-1 voting system in PHP, it should vaguely resemble the SO voting system. On average, it will get about ~100 to ~1,000 votes per item, and will be viewed by many.
I don't know whether I should use:
A database table dedicated for voting, which has the userid and their vote... store their vote as a boolean, then calculate the "sum" of the votes in MySQL.
A text field in the "item" table, containing the uids that already voted (in a serialized array), and also a numeric field that contains the total sum of the votes.
A numeric field in the "item" table, that contains the total sum of the votes, then store whether or not the user voted in a text field (with a serialized array of the poll id).
Something completely different (please post some more ideas!)
I'd probably go with option 3 that you've got listed above. By putting the total number of votes as another column in the item table you can get the total number of votes for an item without doing any more sql queries.
If you need to store which user voted on which item I'd probably create another table with the fields of item, user and vote. item would be the itemID, user would be the userID, vote would contain + or - depending on whether it's an up or down vote.
I'm guessing you'll only need to access this table when a user is logged in to show them which items they've voted on.
I recommend storing the individual votes in one table.
In another table store the summary information like question/poll ID, tally
Do one insert in to the individual votes table.
For the summary table you can do this:
$votedUpOrDown = ($voted = 1) ? 1 : -1;
$query = 'UPDATE summary SET tally = tally + '.$votedUpOrDown.' WHERE pollid = '.$pollId;
I'd go with a slight variant of the first option:
A database table dedicated for voting, which has the userid and their vote... store their vote as a boolean, then calculate the "sum" of the votes in MySQL.
Replace the boolean with an integer: +1 for an up-vote and -1 for a down-vote.
Then, instead of computing the sum over and over again, keep a running total somewhere; every time there is an up-vote, add one to the total and subtract one every time there is a down-vote. You could do this with an insert-trigger in the database or you could send an extra UPDATE thing SET vote_total = vote_total + this_vote to the database when adding new votes.
You'd probably want a unique constraint on the thing/userid pair in the vote tracking table too.
Keeping track of individual votes makes it easy to keep people from voting twice. Keeping a running total makes displaying the total quick and easy (and presumably this will be the most common operation).
Adding a simple sanity checker that you can run to ensure that the totals match the votes would be a nice addition as well.
serialized array: Please don't do that, such things make it very difficult to root around the database by hand to check and fix things, serialized data structures also make it very difficult (impossible in some cases) to properly constrain your data with foreign keys, check constraints, unique constraints, and what have you. Storing serialized data structures in the database is usually a bad idea unless the database doesn't need to know anything about the data other than how to give it back to you. Packing an array into a text column is a recipe for broken and inconsistent data in your database: broken code is easy to fix, broken data is often forever.
I'm working on a PHP app that has several objects that can be commented on. Each comment can be voted on, with users being able to give it +1 or -1 (like Digg or Reddit). Right now I'm planning on having a 'votes' table that has carries user_id and their vote info, which seems to work fine.
The thing is, each object has hundreds of comments that are stored in a separate comments table. After I load the comments, I'm having to tally the votes and then individually check each vote against the user to make sure they can only vote once. This works but just seems really database intensive - a lot of queries for just the comments.
Is there a simpler method of doing this that is less DB intensive? Is my current database structure the best way to go?
To be clearer about current database structure:
Comments table:
user_id
object_id
total_votes
Votes table:
comment_id
user_id
vote
End Goal:
Allow user to vote only once on each comment with least # of MySQL queries (each object has multiple comments)
To make sure that each voter votes only once, design your Votes table with these fields—CommentID, UserID, VoteValue. Make CommentID and UserID the primary key, which will make sure that one user gets only one vote. Then, to query the votes for a comment, do something like this:
SELECT SUM(VoteValue)
FROM Votes
WHERE CommentID = ?
Does that help?
Why don't you save the totaled votes for every comment? Increment/decrement this when a new vote has happened.
Then you have to check if the user has voted specifically for this comment to allow only one vote per comment per user.
You can put a sql join condition which returns all the votes on comments made by the current user for this object, if you get no rows, the user hasn't voted. That is just slightly different from you checking each comment one by one in the program.
as far as the database structure is concerned, keeping these things separate seems perfectly logical. vote { user_id, object_id, object_type, vote_info...)
You may be already doing this, sorry but I couldn't interpret from you post if that was the case.