域名是这样的:
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
另一个很酷的事情是,如果选民人数增加,我可以在恐怖的情况下添加更多的民意调查指数
您如何看待这种方法?
答案 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总计的更新。