什么是民意调查的最佳方式?

时间:2011-09-14 01:59:24

标签: google-app-engine google-cloud-datastore

域名是这样的:

class Poll(db.Model):
    question = db.StringProperty()
    ...

class Choice(db.Model):
    poll = db.ReferenceProperty(Poll)
    choice = db.StringProperty()

class Vote(db.Model):
    user = db.ReferenceProperty(User)
    choice = db.ReferenceProperty(Choice)

(这实际上不是一个确定的模型,它只是伪图)

我需要查询的内容是:

  • 每个投票的总投票数
  • 屏幕上每个投票的每个选项的总投票数
  • 如果当前用户投票,则为每次投票

我已经提出了一些其他模式使用共享计数器,列表属性和没有(我的内在限制)似乎工作。哦,当然,它需要超快:)

你能帮我建模数据吗?

谢谢


编辑:感谢@Nick Johnson我可以更准确地描述我的问题,他建议这个架构

class Poll(db.Model):
    question = db.StringProperty(indexed=False, required=True)
    choices = db.StringListProperty(indexed=False, required=True)
    votes = db.ListProperty(int, indexed=False, required=True)

class Vote(db.Model):
    # Vote is a child entity of Poll, so doesn't need an explicit reference to it
    # Vote's key name is the user_id, so users can only vote once
    user = db.ReferenceProperty(User, required=True)
    choice = db.IntegerProperty(required=True)

问题在于,我无法有效地查询用户是否对特定投票进行了投票。另外,我希望这个shema能够拒绝让每个民意调查1MM票数(或许我永远不会到达那里,但我想瞄准那里)

为了解决这个问题,我想添加一个像这样的EntityIndex:

class PollIndex(db.Model):
    # PollIndex is child of Poll
    voters = db.ListProperty(db.Key)
    voters_choices = db.ListProperty()
    # other search parameters

然后,当我必须查询民意调查列表时,我只能通过2个查询来执行此操作:

# get keys from pollindex where user is not there
# get keys from pollindex where user is there
# grabb all the polls

另一个很酷的事情是,如果选民人数增加,我可以在恐怖的情况下添加更多的民意调查指数

您如何看待这种方法?

1 个答案:

答案 0 :(得分:2)

答案在某种程度上取决于您对投票的最大持续更新率的期望。我假设它最初会非常有限(典型值为每秒1次,峰值高达每秒10次)。

除了几个调整之外,你的设计基本上没问题:

  • 不要将选项存储为单独的实体,只需将它们存储为民意调查中的列表
  • 在民意调查实体上保持总票数以便快速检索

通过这些更改,您的模型看起来像这样:

class Poll(db.Model):
  question = db.StringProperty(indexed=False, required=True)
  choices = db.StringListProperty(indexed=False, required=True)
  votes = db.ListProperty(int, indexed=False, required=True)

class Vote(db.Model):
  # Vote is a child entity of Poll, so doesn't need an explicit reference to it
  # Vote's key name is the user_id, so users can only vote once
  user = db.ReferenceProperty(User, required=True)
  choice = db.IntegerProperty(required=True)

# Here's how we record a vote
def record_vote(poll_key, user, choice_idx):
  # We assume 'user' is an instance of a datastore model, and has a property 'user' that is
  # a users.User object
  poll = Poll.get(poll_key)
  vote = Vote.get_by_key_name(user.user.user_id(), parent=poll)
  if vote:
    # User has already voted
    return
  vote = Vote(key_name=user.user.user_id(), parent=poll, user=user)
  poll.votes[choice_idx] += 1
  db.put([vote, poll])

如果您需要更高的吞吐量,则应将Vote记录修改为不是Poll的子级(并更改其密钥名称以包含轮询ID和用户ID),然后使用具有Memcache或pull队列的后写计数器将结果聚合为Poll总计的更新。