How would you structure a voting system?

Hi there,

I have nodes and relationships like this:

(u:User)
(t:Topic)-[r:HAS_FACT]->(t:Fact)
(t2:Topic)-[r2:HAS_FACT]->(t:Fact)

or, simplified:

(t:Topic)-[r:HAS_FACT]->(t:Fact)<-[r2:HAS_FACT]-(t2:Topic)

Where users can upload Facts and tie them to Topics. Because of the craziness of the internet I'd like to add a voting system that enables users to support/validate/upvote facts, but they don't just upvote the Facts, they need to upvote the combination of Topic and Fact. So really I think they'd be upvoting r and r2?

Essentially I'd like to tie User nodes to some sort of voting system that is somehow tied to a combination of Fact and Topic nodes. I'm not against restructuring anything at this point, happy to do it if there is a more logical solution here!

Thank you in advance!

Hi danfein,

I'm assuming there's a many-to-many relationship between Facts and Topics?
We can extend your data model with a Vote node. Each Fact/Topic pair can have a shared Vote.

(t:Topic)-[:HAS_VOTE]->(v:Vote)<-[:HAS_VOTE]-(f:Fact)
(u:User)-[:VOTED]->(v:Vote)

Hi @jackson1 ,

Great idea, really simple and seems incredibly obvious now. Thank you!

I'm wondering if you can help me take this one step further, because I'm a little confused, hope you don't mind the lengthy post and thank you again and in advance!

The next step I would want to do with this is figure out how to create the Vote nodes, I don't think I want to create them for every Topic & Fact combo unless they're necessary, because it would end up with far too many unused nodes (Vote nodes without votes).

If I were to do this with GraphQL, how would you recommend i approach this? Would you make each vote ID the concatenation of Topic.id and Fact.id, so I can check for its existence more easily? And if it doesn't exist then create it, if it does exist then connect the user node to the Vote node?

And if so, how might you approach all of this with GraphQL, I'm really confused and trying to simplify it with the newly introduced connectOrCreate mutation.

Do I approach it from:

createVotes()
or updateVotes()
or updateUsers()
or updateFacts()

I can't figure out what my top-level would be, this is one attempt but I couldn't get it working. Here I was approaching it through the Facts. Finding the Fact node, then looking to see if I could find a Vote node with a specific ID (here's one of the spots where I'm confused, I would need to know the ID as you can't query inside connectOrCreate by any other property (so do I just concatenation Thing.id + Fact.id?). Then if that node didn't I was creating it and connecting everything all up. Is this reasonable?

updateFacts(
  where: { id: "5d081f2e-7663-4ac1-9c18-f087c35b7042"},
  connectOrCreate: {
    votes: {
      where: { node: { id: "lmnop"}},
      onCreate: { 
        node: { 
          type: "factVote",
          thing: { connect: { where: { node: { id: "21732715-2aa2-4c4b-9c45-ea4985f2113c" }}}},
          detail: { connect: { where: { node: { id: "5d081f2e-7663-4ac1-9c18-f087c35b7042" }}}},
          user_votes: { connect: {where: {node: { id: "YSCbEHFxm0gnXOPEKmRb8WUVO7j2"}}}}
        }
      }
    }
  }
)```

BTW I may be overcomplicating it by merging it into one query, but think ultimately it would be less error prone. I'd rather not check client side to see if the vote node exists, feels like it would be better done at the time the query is run.