0

There are a few questions similar to this already but I am hoping for a somewhat different answer.

I have a website on Google App Engine in Python and I let registered users vote on posts, either up or down, and I only want each user to be able to vote once.

The primary method that I have thought of and read about is to simply keep a list in each post of the users who have voted on it and only show the voting button to users who have not voted yet. To me this seems like an inelegant solution. To keep track of this when hundreds of people are voting on hundreds of posts is a ton of information to keep track of for such a little bit of functionality.

Though I could be wrong about this. Is this as much of a data/datastore write hog as I am imagining it to be? If I have a few hundred votes going on each day is that not such a big deal?

clifgray
  • 4,313
  • 11
  • 67
  • 116
  • If you prefer, you could have the list against each user (so it tracks the ids of the posts that the user has voted on). That's a little more convenient to work with, but it's still essentially the same solution. – aroth Oct 15 '12 at 04:57

3 Answers3

3

Create a Vote Kind that looks something like this:

class Vote(db.Model):
    value = db.IntegerProperty() # Or whatever the vote value is.

The trick is to generate the Key for the vote as a combination of the User and Post ids.

keyname = str(user.id) + "-" + str(post.id)
vote = Vote.get_or_insert(keyname, value="vote value")

This way you can quickly check if a user has already voted on a given post.

dragonx
  • 14,963
  • 27
  • 44
  • I suppose the get_or_insert function is something I should write? it should be easy enough I just wanted to make sure something like that didn't exist already, though I couldn't find it in the docs – clifgray Oct 15 '12 at 15:45
  • https://developers.google.com/appengine/docs/python/datastore/modelclass#Model_get_or_insert – dragonx Oct 15 '12 at 15:54
  • okay great. wouldn't I have to do: Model.get_by_key_name() to see if it exists first? it doesn't seem like Model.get_or_insert() is actually able to tell you whether it exists or not it just simply returns the entity either way – clifgray Oct 15 '12 at 16:52
  • My bad, you're right. get_or_insert() isn't the right thing for you. Yes, you would need to do get_by_key_name(), but they important part of my answer was to use an simple entity where the keyname matches what you're looking for so you don't need to issue a fancy query. – dragonx Oct 15 '12 at 17:47
  • great, I can work it out from there I just needed some inspiration. thanks for the help! – clifgray Oct 15 '12 at 18:19
0

Have you tried set() variable type which avoid duplicate?

Arnaud Aliès
  • 1,079
  • 13
  • 26
0

If you only have hundreds of votes for hundreds of posts this is not a big data hog or read/write hog. I am assuming you are storing the list of users as a list in the post enity on the data store. Depending on if you are storing a long that points to the user or a string for their email you are probably at most using 10 bytes per user per post. if you have a thousand votes per post and 1000 posts then you would be using 10 MB. Plus it wouldn't add much to the cost of read/writes. You could reduce that cost if you want by not indexing the value and just search through it when you get it from the data store for the needed information.

Michael
  • 1,321
  • 1
  • 13
  • 27