域名如下:
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)
这样做的问题是,我无法有效地查询显示用户是否对特定的投票进行了投票。此外,我希望这个模式能够抵抗,比如每次投票100万票或其他(也许我永远不会达到那里,但我想瞄准那里)
为了解决这个问题,我正在考虑添加这样一个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次,峰值高达每秒10次)。
你的设计基本上是好的,除了几个调整:
- 不要将选择存储为单独的实体,只需将它们存储为民意调查中的列表
- 保持在Poll实体上的投票总数,以便快速检索
通过这些更改,您的模型看起来像这样:
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
的子记录(并将其键名更改为包含poll ID和用户ID),然后使用Memcache的write-behind计数器或pull队列将结果聚合为poll总数的更新。