Reputation: 27
I am trying to make a website containing posts so I have a 'Read more' link which expands the content there and there only like quora. How do I know the total number of times it has been clicked so that I can display the views?
I am using nodejs, express and mongodb as the server.
This is my hbs (handlebars) file with that read more link
<p class="startPara">{{stripTags (truncate body 200)}}<span class="dots" >...
</span></p>
<span class="content">
<p>{{stripTags (truncate body 400)}}</p>
</span>
<a onclick="readMoreFunction(this)" class="buttonReadMore" >Read more</a>
</div>
This is my main hbs file which executes all the js its script tags
<script>
function readMoreFunction(el) {
var parent = el.closest(".wrapper")
var dots = parent.querySelector(".dots");
var contentText = parent.querySelector(".content");
var btnText = parent.querySelector(".buttonReadMore");
var startPara=parent.querySelector(".startPara");
btnText.style.display = "none";
startPara.style.display= "none";
dots.style.display = "none";
contentText.style.display = "inline";
}
</script>
Now every post is unique clicked by a unique user so just incrementing a variable won't help.
So please tell me how to calculate the total number of times that link has been clicked for a specific post and then how to communicate it to the database so that I can display it on the webpage
Upvotes: 1
Views: 2967
Reputation: 41
Store an object in the viewers session and db column called 'viewed_posts'. Use the object to determine whether they viewed a post or not.
if (typeof(req.session.viewed_posts[post_id]) == 'undefined') {
req.session.viewed_posts[post_id] = 1; //update session
//increment post count in posts table with post id
//update 'viewed_posts' column with new session
}
//select post
When the object in 'viewed_posts' gets too large (say 3000 posts viewed), delete it. If the average viewer reads 2 unique posts a day, it will be 4.5 years until the second unique view MIGHT occur on the same post.
Although this does not guarantee uniqueness forever (still a long time), it is much more efficient because..
You avoid a views table completely
The views count in the posts table is a single number (No searching)
The viewer does not have to search a table to see if they already viewed a post. They just have to refer to their session.
Use varchar(x) AND the incremented id NOT the uuid to store the object.
OR (my preferred way)
Go vice versa and store an object in the row of the post, select that, parse it, check if you are there, if not there insert self and on the client, use object.keys to get how many views the post has. When the object is too large, delete the key value pairs which are the oldest and increment a count by one in another column (add keys and count) OR stop adding key value pairs.
OR
use a join clause when you select with views table
select * from posts as p LEFT JOIN views as v ON p.post_id = post_id AND p.post_id = v.post_id AND v.view_id = my_id LIMIT 2
//if the result length is 1, insert self into views
//if the result length is 2, you know that you have already viewed (don't insert)
//select post view count and return result[0] from above with count
OR
don't use a join with views table
post = select * from posts where post_id = post_id
if_viewed = select COUNT(*) from views where post_id = post_id AND view_id = my_id
(if count is 0 insert into views)
post_views = select COUNT(*) from views WHERE post_id = post_id
//return post and post_views
Upvotes: 1
Reputation: 9474
Realistically, this is very complex topic.
Naive: have button click send a ping to the dedicated backend endpoint that updates the database. Think about multiple clicks (because the user is bored), other ways to read full posts, etc.
Practical: consider Google Analytics and such.
Do not: count requests on the server. Browsers do weird stuff (preflight requests, different previews, etc). Number of requests may not correspond to the number of views.
Upvotes: 1
Reputation: 1123
I imagine you would need to have a 'views' property on your Post in MongoDB.
You could serve the first 400 characters for each post in your getPosts
api request.
Clicking read more could call getPost(id)
on your api, returning the full post payload, during that process you could increment post.views by one.
Additionally as @tobiv suggests in the comments you could have code that ensures only unique visitor clicks are counted.
Upvotes: 1