【发布时间】:2013-12-31 01:49:27
【问题描述】:
作为in this post 的延续,这是一个有点顶峰式的问题,可以巩固我对gae-datastore 的理解,并对我的数据建模决策提出一些批评。我将修改 @Jimmy Kane 创建的 Jukebox 示例,以更好地反映我的真实案例。
在原始设置中,
假设您有一个自动点唱机,每个房间都有队列。人们正在将歌曲排队到每个点唱机的每个队列中。
J=Jukebox, Q=queue, S=Song
Jukebox
/ | \
Q1 Q2 Q3
/ | \ | \
S1 S2 S3 S4 S5
首先,这样填写 Song 模型:
Song(ndb.Model):
user_key = ndb.KeyProperty()
status = ndb.StringProperty()
datetime_added = ndb.DateTimeProperty()
我的修改是添加一个User,可以CUD歌曲到任何队列。在前端,用户将访问 UI 以查看每个队列中的歌曲并进行更改。在后端,应用程序需要知道每个队列中有哪些歌曲,从每个队列中播放正确的歌曲,并在播放后从队列中删除歌曲。
为了让用户能够在队列中看到其歌曲,我假设每个用户都是根实体,并且需要存储歌曲键列表
User(ndb.Model):
song_keys = ndb.KeyProperty(kind='Song', repeated=True)
然后,为了检索用户的歌曲,应用程序将(假设 user_id 已知)
user = User.get_by_id(user_id)
songs = ndb.get_multi(user.song_keys)
而且,由于gets 是强一致的,用户将始终看到非陈旧数据
然后,当队列 1 播放完歌曲后,应用程序可以执行以下操作:
current_song.status = "inactive"
current_song.put()
query=Song.query(ancestor=ndb.Key('Jukebox', '1', 'Queue', '1')).filter(Song.status=="active").order(Song.datetime_added)
next_song = query.get()
我认为祖先查询确保当前歌曲的先前停用以及来自用户的任何 CUD 的一致表示是否正确?
最后一步是在交易中更新用户的 song_keys 列表
user = current_song.user_key.get()
user.song_keys.remove(current_song.key)
user.put()
总结和一些优点/缺点
- 一致性似乎是在正确的地方做正确的事 如果我的理解是正确的?
- 我应该关注
Jukebox实体组的争用吗?- 我不希望它是一种高吞吐量类型的用例,但我的现实生活场景需要随着用户数量而扩展,
queues 的数量可能与user的数量相似s,users 可能比queues 多 2 到 5 倍。如果整个组被限制为 1 次写入/秒,并且很多用户以及每个队列都可能在创建和更新歌曲,这可能是一个瓶颈 - 一种解决方案是取消
Jukebox根实体,让每个Queue成为自己的根实体
- 我不希望它是一种高吞吐量类型的用例,但我的现实生活场景需要随着用户数量而扩展,
-
User.song_keys可能很长,比如 100song.keys。 This article 建议“避免在 ListProperty 中存储过大的键列表”。这里有什么顾虑?这是一个 db 概念吗? ndb 使用repeated=True属性选项处理列表的方式?
对这种方法的意见或对我根本误解的事情的批评?
- 大概,我也可以选择,只是对称翻转
数据模型和实体组看起来像
User->Song并将song_keys列表存储在Queue模型中
【问题讨论】:
标签: gae-datastore python entity-framework google-app-engine data-structures google-cloud-datastore