• Home
  • Categories
  • Recent
  • Popular
  • Top
  • Tags
  • Users
  • Groups
  • Documentation
    • Home
    • Read API
    • Write API
    • Plugin Development
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
v3.5.2 Latest
Buy Hosting

Manually setting vote count for posts

Scheduled Pinned Locked Moved Unsolved Technical Support
19 Posts 2 Posters 224 Views
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    razibal
    wrote on last edited by razibal
    #1

    Is there any way I can set vote counts for imported posts without having to import the users that created them? Perhaps assign them to an 'anoymous' or 'generic' user? I can create a proxy user, but since a user can only upvote a post once, I'm not sure if there is a way to set the starting vote count to the existing votes in the imported posts.

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #2

    If you know the values you can just set them directly on the post objects. The fields are upvotes & downvotes on post objects.

    So an upgrade script can do

    await db.setObject(`post:${pid}`, { 
      upvotes: numberOfUpvotesFromImport,
      downvotes: numberOfDownvotesFromImport,
    });
    

    The value displayed on nodebb UI is calculated from upvotes - downvotes

    R 1 Reply Last reply
    2
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by
    #3

    @baris Thanks, that works, but only for static imports. If I let current users vote on an imported post the vote count gets reset. I do have a custom field that stores the imported vote counts, is there a hook I can use to update the displayed votes to include this value along with the 'real' count?

    Also, assuming I lock down the imported posts so no one can vote on them, is there a way to see the statically set vote count reflected on the category view? The topic still shows the 'real' vote count.

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #4

    On the category page each topic object has upvotes/downvotes/votes fields as well this comes from the main post of the topic.

    You are right about votes resetting if someone votes on it. It is hard to fix that without setting the pid:<pid>:upvote & pid:<pid>:downvote sets. These sets contain uids who have upvoted/downvoted the post. If you don't import the users then these don't exists and if someone votes on a post again then the count gets reset.

    The best hook to modify post objects loaded in a topic is filter:post.getPosts

    R 1 Reply Last reply
    1
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by
    #5

    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.

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #6

    @razibal see this topic https://community.nodebb.org/post/95161 for a plugin that does that.

    R 2 Replies Last reply
    2
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by
    #7

    That will work perfectly. I'll create a custom topic field for the total imported votes and add them to the calculated votes.

    Appreciate the help!

    1 Reply Last reply
    2
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by
    #8

    @baris This works, however the soring by votes still seems to be using the votes on the main post. Where is the logic for sorting handled?

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #9

    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 uses cid:<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.

    1 Reply Last reply
    0
  • R Offline
    R Offline
    razibal
    wrote on last edited by
    #10

    @baris, if we ignore my imported votes, should it be using the calculated/cumulative totals or are they still sorted by the votes on the main post?

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #11

    They are sorted by whatever score is set in that sorted set and that score is right now is the score of the main post. https://github.com/NodeBB/NodeBB/blob/master/src/posts/votes.js#L292

    1 Reply Last reply
    0
  • R Offline
    R Offline
    razibal
    wrote on last edited by
    #12

    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.

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by baris
    #13

    It works the same as redis in mongodb you just add an element with db.sortedSetAdd('someSet', 123, 'item1'); and when you retrieve it with db.getSortedSetRange('someSet', 0, -1) it will be in the correct order. It is handled by the _key, score compound index on the objects collection.

    1 Reply Last reply
    0
  • R Offline
    R Offline
    razibal
    wrote on last edited by
    #14

    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

    barisB 1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    replied to razibal on last edited by
    #15

    @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 😆

    R 1 Reply Last reply
    0
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by
    #16

    @baris

    @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 🙂

    1 Reply Last reply
    0
  • R Offline
    R Offline
    razibal
    wrote on last edited by
    #17

    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 script

    However, 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 the src/posts/votes.js module. It's going to need to sum all the votes in the topic and set that as the cid:${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.

    1 Reply Last reply
    0
  • barisB Offline
    barisB Offline
    <baris> NodeBB
    wrote on last edited by
    #18

    You can probably use this hook to do the recalculation https://github.com/NodeBB/NodeBB/blob/master/src/posts/votes.js#L267

    R 1 Reply Last reply
    2
  • R Offline
    R Offline
    razibal
    replied to <baris> on last edited by razibal
    #19

    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)
    }
    
    1 Reply Last reply
    2

Copyright © 2023 NodeBB | Contributors
  • Login

  • Don't have an account? Register

  • Login or register to search.
Powered by NodeBB Contributors
  • First post
    Last post
0
  • Home
  • Categories
  • Recent
  • Popular
  • Top
  • Tags
  • Users
  • Groups
  • Documentation
    • Home
    • Read API
    • Write API
    • Plugin Development