MyBB Community Forums

Full Version: [Suggestion] Unique Views
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi. Right now there is an option to see amount of views that thread has, but those views are not unique, meaning that every time I'm re-visiting same thread it gets +1. I was thinking that it would be good to add option to get another column that would be "Unique Views", which would get +1 only once, when user opens/reads thread for the first time. 


I have literally no clue how this all forum stuff is written, I don't even know what language is used, or whatever. But still I was thinking of a way to implement it, and I've came with this:

P.S.: it's pseudo-code in c++, but I'm sure it's possible to implement on pretty much almost anything

when user opens thread, there goes the following "if"

if (userType != guest && isUnique(userID, threadID))
{ // if there is no such thing as usertype, it can be changed to a function that checks if whoever viewing this thread has an id
    uniqueViews++;
    addToUniqueList(userID, threadID)
}

bool isUnique(int userID, int threadID) // threadID is an array. should have been pointer to array but  i dont want to make it here now
{ //checks if user id is in the list of people who visited it
    for (int i = 0; i < threadID.size(); i++)
       if (userID == threadID[i])
           return false;
    return true;
}

void addToUniqueList(int userID, int threadID) // finds first empty space in an array and fills it with user id
{
    for (int i = 0; i < threadID.size(); i++)
        if (threadID[i] == 0)
           {
               threadID[i] = userID;
               break;
           }
}
It's definitely doable, but it would be slower which might result in negative repercussions for big boards.

You would need a database table with two columns, a userID and a topicID. Instead of a regular increment query, you would need a subquery which checks whether an entry exists in that table and inserts if so. And then, MyBB would sniff out if it managed to insert anything and increment the unique view column, you might also need a transaction there to prevent a data race where topics sometimes get incremented twice for the same user, but that would result in a lock being acquired for that topic while it does that.

Maybe, some stuff can be reused from the read / unread thread system?

Edit: Might be able to avoid a transaction with a subquery computing the number of views for that topic on the spot and feeding that through to an update. E.g. UPDATE topics SET uniqueviews = (SELECT COUNT(*) FROM uniqueviews WHERE uid = ? AND tid = ?) WHERE tid = ?

But a sub-query increment + an insert on every topic view is pretty heavy compared to a simple increment.

Edit: Looked up the subquery syntax. Amended the example. Also, that example doesn't track guests.

I just looked at your C++ example, that would be problematic, as it's O(n), so it would get exponentially slower as the array gets bigger and bigger. While there are *better* algorithms for that, PHP doesn't allow us to store things in persistent memory like that, and it would be tricky to wrangle as it is there due to concurrency.
Yea, true. I haven't even given a single thought about execution time for huge forums, where there are hundreds of new unique views every day.

Interesting idea about read/unread thread system. What about adding new flag or something, that would go like "You've read this thread before". I mean, there are such flags as "Contains Posts by you", "Hot thread", "New posts", there can be added new thing called "Visited by you before".

Nice idea.
(2017-12-03, 03:44 AM)Azah Wrote: [ -> ]It's definitely doable, but it would be slower which might result in negative repercussions for big boards.

You would need a database table with two columns, a userID and a topicID. Instead of a regular increment query, you would need a subquery which checks whether an entry exists in that table and inserts if so. And then, MyBB would sniff out if it managed to insert anything and increment the unique view column, you might also need a transaction there to prevent a data race where topics sometimes get incremented twice for the same user, but that would result in a lock being acquired for that topic while it does that.

Maybe, some stuff can be reused from the read / unread thread system?

Edit: Might be able to avoid a transaction with a subquery computing the number of views for that topic on the spot and feeding that through to an update. E.g. UPDATE topics SET uniqueviews = (SELECT COUNT(*) FROM uniqueviews WHERE uid = ? AND tid = ?) WHERE tid = ?

But a sub-query increment + an insert on every topic view is pretty heavy compared to a simple increment.

Edit: Looked up the subquery syntax. Amended the example. Also, that example doesn't track guests.

I just looked at your C++ example, that would be problematic, as it's O(n), so it would get exponentially slower as the array gets bigger and bigger. While there are *better* algorithms for that, PHP doesn't allow us to store things in persistent memory like that, and it would be tricky to wrangle as it is there due to concurrency.

Don't lock the row, rather let it run as normal and add a task that checks for duplicates and recounts the thread views.
But you don't know which ones have been over-counted (due to multiple threads inserting the exact same unique view at the same time, possible if someone bots it or spams the refresh button), so the task would essentially rebuild the entire unique view cache.

Normally, I'd say that tasks are fairly light, but there could be millions of unique view records. I guess, there could be a flag on the row to say whether it's been processed and it would cover everything, although it might miss a view here and there in extremely unlikely cases (a user viewing a topic multiple times simultaneously at the exact same time the tasks run).
Might not need a lock there, as the database might take care of it for you for increments at-least, concurrency makes my head spin. Either way, this stuff is slow.
I think this might be a very good suggestion and I feel if we add a option in forum settings, it will be good Smile
Or it might be a good option as a plugin.