开发者

Modeling Votes on GAE

I'm trying to determine the most efficient way to create a votable entity on GAE's datastore. I would like to show the user a control to vote for th开发者_C百科is entity or an icon indicating that they have already voted for it; ie, I'm asking "has a user voted on this entity?" Lets say that we have a Question entity that a user may up-vote. Here is what I'm thinking of doing:

  1. Query for my Question entities. These questions already have a precalculated ranking on which I will sort.
  2. Use a relation index entity that is a child of the Question entity. Query for all Questions using the same filters as #1 where my user is a member of this relation index entity.
  3. Merge the results of #2 into #1 by setting a hasVoted property to true for each found set member.

This is the cleanest way I could think of doing it but it still requires two queries. I didn't to create duplicate Question entities for each user to own because it would cause too much data duplication. Is this solution a good way to handle what is effectively a join between a m2m relationship between Votes and Questions or am I thinking too relationally?


Instead of using a relation index, just have a child entity for each user that's voted on the question. Make the key_name of the child entity the ID of the user. Then, to determine if a user y has voted on a question with ID x, simply fetch the key (Question:x/Vote:y). You can batch this to fetch multiple entities for multiple questions or users, too.


I would take a look to Overheard Google App Engine sample application.

Our basic model will be to have Quotes, which contain a string for the quotation, and Votes, which contain the user name and vote for a particular user.

There's a Google article about it and here you can find the sources.


To avoid the second query, you could store all of the questions a user has voted on in a single entity. This entity could be part of the User model, or exist in a one-to-one relationship with User entities.

You could then load this information as needed (and store it to memcache to avoid datastore loads) so that you can quickly check if a user has already voted on a question (without doing a second query most of the time).

If a user may vote on a really large number of questions, then you may have to extend this idea. Here is an outline (not functionally complete) of how you might go about the simple scheme:

class UserVotes(db.Model):
    # key = key_name or ID of the corresponding user entity

    # if all of your question entities have IDs, then voted_on can be a list of 
    # integers; otherwise it can be a list of strings (key_name values)
    voted_on = db.ListProperty(int, indexed=False)  

# in your request handler ...
questions = ...
voted_on = memcache.get('voted-on:%s' % user_id)
if voted_on is None:
    voted_on = UserVotes.get_by_id(user_id)  # should do get_or_insert() instead
    memcache.set(...)
for q in questions:
    q.has_voted = q.key().id() in voted_on
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜