Manually setting vote count for posts
-
I think I can sort of get what I need by using that hook and just displaying the adjusted vote count
hookData.posts.map( post => { post.votes = post.votes + post.importedVotes})
I didn't know that the category view only displays the vote count for the main post. Is there an option to use the total votes for the posts in the topic? My thinking is that if a user is sorting by 'Most Votes', it makes sense to use the cumulative votes.
-
On category pages it's in handled by
Categories.getTopicIds
it uses a sorted set based on how the user wants the topics to be sorted. If you want to sort by votes it usescid:<cid>:tids:votes
the scores in there determine how they are sorted. In this case the scores don't have your imported values so that's why it doesn't work. -
Apologies for all the questions, but I am trying to understand how simulated sorted sets work in MongoDB. In Redis, inserting an element into a sorted set is handled by the DB as it gets placed in the right ranking order based on the score. How does this work with MongoDB? Is the entire set recreated when a score changes or a new element needs to be added? I can lock down the voting on imported topics, but I do need to set the correct values in the
cid:<cid>:tids:votes
set on import. -
It works the same as redis in mongodb you just add an element with
db.sortedSetAdd('someSet', 123, 'item1');
and when you retrieve it withdb.getSortedSetRange('someSet', 0, -1)
it will be in the correct order. It is handled by the_key, score
compound index on the objects collection. -
Cool, and I assume that adding an element that already exists is handled transparently ( score gets updated ). By the way, have you, or anyone else, tried nodeBB with tidis https://github.com/tidb-incubator/tidis
-
@razibal said in Manually setting vote count for posts:
Cool, and I assume that adding an element that already exists is handled transparently ( score gets updated )
Yeah it just updates the score if it's already in the zset.
I haven't looked at tidis, to be honest we have enough database adapters to deal with already
-
@baris said in Manually setting vote count for posts:
I haven't looked at tidis, to be honest we have enough database adapters to deal with already
Understandable, only reason I brought it up is because it appears that all the adapters are essentially emulating Redis, and Tidis promises 100% protocol compatibility while addressing the negatives of Redis. I will admit using MongoDB as a Redis replacement has been a little bit frustrating for me because none of the collection structures look like what I would expect them to in MongoDB
-
I was able to set the imported vote count in the import script by adding
await db.sortedSetAdd(`cid:${topic.cid}:tids:votes`, post.importedVotes, post.tid)
to the scriptHowever, it doesn't look like there is any way to get 'Sort by Most Votes' (using all votes rather that just the main post votes) to work without modifying the
updateTopicVoteCount
function in thesrc/posts/votes.js
module. It's going to need to sum all the votes in the topic and set that as thecid:${topicData.cid}:tids:votes
value.This is an example of a use case where being to override a core method or function would be really useful.
-
Thanks, that works perfectly. I'm handling the hook in my custom theme, but this probably needs to be in the https://community.nodebb.org/post/95161 plugin as well (without the importedVotes)
library.setTopicVotes = async function(hookData) { const topicData = await topics.getTopicFields(hookData.post.tid, ['cid', 'importedVotes']); const importedVotes = topicData.importedVotes || 0 const voteData = await db.getSortedSetRangeByScoreWithScores(`tid:${hookData.post.tid}:posts:votes`, 0, -1, 1, '+inf'); let allvotes = voteData.reduce((acc, cur) => acc + cur.score, 0); allvotes = allvotes + importedVotes await db.sortedSetAdd(`cid:${topicData.cid}:tids:votes`, allvotes, hookData.post.tid) }