I am working on a social network website project. I have created database and everything.
The posts table has a preference column which stores the preference value according to the likes and comments that a post gets from the users and also the time at which the post is created.
To retrieve posts for a user's home page from the posts table, I am running a query using joins which sorts using preference column .
Now, suppose I retrieve 10 posts for a user to be shown on the posts table and user scrolls down and one more request is made from the user to retrieve next 10 posts to the server.
If in between of those requests few other users creates a new post or preference value of posts in the database changes in the between, and now if I the second request is run on the server, all the posts will be resorted for the second request (i.e. to show next 10 posts) but since the database is updated , this means in the second request there will be many chances that few of earlier 10 posts are retrieved along in the second request.
I want to know how to avoid these duplicate requests.
How facebook or any other social network solves this problem at the backend when their database is dynamic.
I would rather avoid such unreliable way of sorting at all.
As a user, I'd rather quit that service. Frankly, I hate such too smart a service which decides which posts I have to see and which not. And even dynamically ordered on top of that.
Make it ordered by date, by tags of interest, by something sensible, reliable and constant.
In your script store a record of the rows id returned.
For example, using a basic limit and just storing the latest id when the first select is done, and using the page number to determine the limit of records to return.
SELECT id, somefield
FROM SomeTable
WHERE id < $SOMESTOREDVALUE
LIMIT $PAGENUMBERTIMESTEN, 10
or storing the latest id after each page is returned (which you will need to store each time this is run)
SELECT id, somefield
FROM SomeTable
WHERE id < $SOMESTOREDVALUE
LIMIT 0, 10
If you store the time & date when the user first makes a request in a session, you could use that to filter the posts table.
So your SQL for the second page of results would be along the lines of
SELECT <some fields> FROM <sometables>
WHERE DatePosted <= $timefirstseen LIMIT 10, 10
Where $timefirstseen was loaded from the session variable. This will restrict your results to only posts that existed when the users visit started.
You would of course need to include a feature to allow the user to clear the session or do that automatically when they revisit their homepage to make sure they got to see the new posts eventually!
Related
I have a screen that looks very much like facebook timeline
users can view posts of other users etc.
to get these posts i do something like
select user.id,user.name,posts.title,posts.body from posts left join users;
now data i need to collect is "Who saw this post" .
is there any elegant way to do it ?
right now all what i can think of is every time i fetch posts. i loop over them, then collect all ids of posts that the query returned and then push in another table
user_views [pk:user_id+postId]
userId,postId
1 , 1
Then when i'm fetching posts next time i can do count of user_views.
select *,count(user_views.id) from posts join user_views on post_id = post.id
but this sound like a lot of work for each VIEW, specially that most probably user will see a most multiple times,
is there any known patterns for such need ?
This is a design question and the answer really depends on your needs.
If you want to know exactly who viewed what post and how many times, then you need to collect the data on user - post level.
However, you may decide that you do not really care who viewed which post how many times, you just want to know how many times a post was viewed. In this case you may only have a table with post id and view count fields and you just increment the view count every time a post is being viewed.
Obviously, you can apply a mixed approach and have a detailed user - post table (perhaps even with timestamp) and have an aggregate table with post id and view count fields. The detailed table can be used to analyse your user's behaviour in a greater detail, or present them a track of their own activities, while your aggretage table can be used to quickly fetch overall view counts for a post. The aggregate table can be updated by a trigger.
I have a website where people can make posts and follow other users. I have a sidebar that has a value that keeps track of the number of posts that have been posted since your last visit.
I'm stuck thinking of how I should handle this. Should I create an entirely new table in the database called notifications that would hold the user's id and the number of posts since last visit, should I just add a column in the existing user table for this value, or should I use an entirely different method?
Thanks.
First of all: Think, which object this is a property of. In your case, the count will differ from user to user, so we might assume, it is a user property.
We could hang it on the last login, but this would give us a wrong count, if the user is logged in for a long period (The user doesn't want to know the count since his last login, but since his last activity!).
So the easiest way could be to add a field to the users table, that holds the last post ID - We just SELECT MAX(id) FROM posts and update users.lastSeenPost with the result on every user action. We can then display MAX(post.id)-users.lastSeenPost as the new post count.
Every post has a date recording when it was made.
Every user will have a date keeping track of when he/she logged in the last time.
By the following SQL statement you could ask the database to return the number of posts since the user logged in last:
SELECT COUNT(*) FROM `posts` WHERE `posts.post_date` > `user.lastlogin_date`
I suggest that you will create a cookie ($_COOKIE['lastPostId']) in each customer webbrowser with the LAST ID of your posts, and, when the user return, you will read $_COOKIE['lastPostId'] and query your database as SELECT * FROM posts WHERE id>lastPostId
As title, when I have a content list, but not everybody can see them.
For example:
I have group 1 and group 2
I create a post, only the users in group 1 can see it.
I create another post, only the users in group 2 can see it.
User 1 in group 1, User 2 in group 2.
Then, when user 1 looks at the newest content list, he can only see the post 1.
Then, user user 2 looks at the newest content list, he can only see the post 2.
You can see, different account (user) will see different post in his/her post list. Because I store all posts in one table, and I store the group_id in it, when creating the newest post list for a user, I have to search all newest post and check one by one if the user can see it or not, if there are too many posts which he don't have permission, the performance will be very bad.
Also, the group is not static in some cases, such as: my followers, my friends, if so, I still can't store the user id in post table, and have to calculate their relationship to determine he/she can read this post or not. and again, the post can be with multiple-permission groups (my followers and my friends can see it).
How can I improve it?
BTW, why I don't insert the user_id array in post record, because maybe the number of group users is very big, so I can only save group_id in it.
BTW again,
I have one SNS website.
I use mongodb database.
I use php.
When user authorizes, store his group_id in session data. Then you can use that group_id when you generate your menu, make it an extra condition in your database query to get only posts that are allowed to this group to be seen.
If the user is not authorizes, you can use some default group_id value to show only posts, allowed for everyone to view.
For complex conditions like the ones you have I'd recommend using UNION if you had mysql, but looks like you will simply need to do multiple queries. First, separate all possible different conditions on which content groups should be available to a specific user.
For example: if user can only see content from his group, his friends and people he follows, you can simply do 3 requests (get content list of his group, posts of people he follows and posts of his friends) and then combine that data with PHP and output it. Since all the data is the same (as you said - it all is in posts table) you won't need anything fancy here. Just three request and sorting the way you want on php side.
I'm trying to create a filter to show certain records that are considered 'trending'. So the idea is to select records that are voted heavily upon but not list them in descending order from most voted to least voted. This is so a user can browse and have a chance to see all links, not just the ones that are at the top. What do you recommend would be the best way to do this? I'm lost as to how I would create a random assortment of trending links, but not have them repeat as a user goes from page to page. Any suggestions? Let me know if any of this is unclear, thanks!
This response assumes you are tracking up votes in a child table on a per row basis for each vote, rather than just +1'ing a counter on the specific item.
Determine the time frame you care about the trending topics. Maybe 1 hour would be good?
Then run a query to determine which item has the highest number of votes in the last hour. Order by this count and you will have a continually updating most upvoted list of items.
SELECT items.name, item_votes.item_count FROM items
INNER JOIN
(
SELECT item_id, COUNT(item_id) AS item_count
FROM item_votes
WHERE date >= dateAdd(hh, -1, getDate()) AND
## only count upvotes, not downvotes
item_vote > 0
group by item_id
) AS item_votes ON item_votes.item_id = items.item_id
ORDER BY item_votes.item_count DESC
You're mentioning that you don't want to repeat items over several pages which means that you can't get random ordering per request. You'll instead need to retrieve the items, order them, and persist them in either a server-wide or session-specific cache.
A server-wide cache would need to be updated every once in a while, a time interval you'll need to define. Users switching page when this update occurs will see their items scrambled.
A session-specific cache would maintain the items as long as the user browses your website, which means that the items would be outdated if your users never leave. Once again, you'll need to determine a time interval to enforce updates.
I'm thinking that you need a versioned list. You could do the server-wide cache solution, and give it an version (date, integer, anything). You need pass this version around when browsing the latest trends, and the user will keep viewing the same list. Clicking on the Trends menu link will send them to the browsing pages without version information, which should grab the latest from your cache. You then keep this as long as the user is browsing these pages.
I can't get into sql statements, not because they are hard, but we don't know your database structure. Do you keep track of individual votes in a separate table? Are they just aggregated into a single column?
Maybe create a new column to record how many views it has? Then update it every time someone views it and order by threads with the largest number of views.
I am trying to build a website with mysql and php. This is the first site I have attempted so I want to write a little plan and get some feedback.
The site allows users to add some text in a text field as a “comment”. Once the comment has been entered into the site it is added to the database where it can be voted for by other users.
When a new comment has been added to the database it needs to create a new page, e.g. www.xxxxx.com/commentname or www.xxxxxx.com/?id=99981.
There will be a list of "Comments" in the database along with the number of votes for each comment.
The home page will have two functions.
1) Allow users to add a "comment"
2) Display two tables, each with 20 rows containing most "popular comments" and "recent comments"
Each comment will generate its one page where the comment will be displayed. Here users can read the comment and Vote for the comment if they wish.
Please help me out by explaining how to do the following.
-Generate a new page whenever a comment is added to the database
-Add a vote to the vote count in the comment database.
-Display the top 20 most popular comments as per number of votes.
-Generate a new page whenever a comment is added to the database
You only need a comment.php file with a MySQL query getting the given comment out of the database. I would recommend to use the comments primary key to get the comment. Using rewrites you can have a URL like this: www.xxxx.com/comment/1. If you need the redirect for a specific link structure ask again.
-Add a vote to the vote count in the comment database.
Just add a column to your table holding the votes. If you have logged in users and you want then to check their votes, create a new table for the votes and another table for the many to many realtion.
-Display the top 20 most popular comments as per number of votes.
This is simply done by sorting in the MySQL queries and selecting only 20 results:
// For the recent 20 comments
SELECT * FROM comments ORDER BY id DESC LIMIT 0,20
// For the 20 most popular comments
SELECT * FROM comments ORDER BY votes DESC LIMIT 0,20
Any further questions?
This is a pretty broad question, i don't think we'll be able to help you fully here at stack without making a full blown php blog tutorial!
I'll try and point you in the right direction however. Firstly i'd say take a look at wordpress, even though i presume you want to make your own custom one, wordpress would be a good starting point for code inspiration? (Just a thought)
The way i'd generate a new page, would be to make a php page, say comments.php, which using the $_GET variable, gets the related record in the database and displays it.
Adding a vote up or down is as simple as adding form to the page with two submit buttons, one with a value of 1 one with a value of -1, upon submit it sends its value to the database, and takes the existing vote value say 25 and adds its value so, if u up voted 25 + 1 = 26 if you downvoted 25 + -1 = 24.
Displaying the 20 most popular comments is just a case of using some SQL sorting, something like this would work
SELECT * FROM comments ORDER BY votes DESC LIMIT 0, 20
That statement selects all the columns from the comments table, sorts it by the votes column decending, so highest value first, and then limits the number of records it fetches by 20, from there its a case of looping through each record and displaying it how you wish.
I hope this atleast gets you started on the right path :)