考虑一个允许用户评论歌曲的GAE(python)应用程序。预期用户数量为1,000,000+。预计的歌曲数量是5000。如何计算Google App Engine中多对多关系的双方
应用程序必须能够:
- 给歌曲的用户已经对
- 评论数给谁有一首歌
计数器管理必须评论的用户数是事务性的,以便它们始终反映基础数据。
看起来,GAE应用程序必须始终保持这些计数类型的计数,因为在请求时查询它们将是低效的。
我的数据模型
class Song(BaseModel):
name = db.StringProperty()
# Number of users commenting on the song
user_count = db.IntegerProperty('user count', default=0, required=True)
date_added = db.DateTimeProperty('date added', False, True)
date_updated = db.DateTimeProperty('date updated', True, False)
class User(BaseModel):
email = db.StringProperty()
# Number of songs commented on by the user
song_count = db.IntegerProperty('song count', default=0, required=True)
date_added = db.DateTimeProperty('date added', False, True)
date_updated = db.DateTimeProperty('date updated', True, False)
class SongUser(BaseModel):
# Will be child of User
song = db.ReferenceProperty(Song, required=True, collection_name='songs')
comment = db.StringProperty('comment', required=True)
date_added = db.DateTimeProperty('date added', False, True)
date_updated = db.DateTimeProperty('date updated', True, False)
代码
此处理用户的歌曲算事务而不是歌曲的用户数。
s = Song(name='Hey Jude')
s.put()
u = User(email='[email protected]')
u.put()
def add_mapping(song_key, song_comment, user_key):
u = User.get(user_key)
su = SongUser(parent=u, song=song_key, song_comment=song_comment, user=u);
u.song_count += 1
u.put()
su.put()
# Transactionally add mapping and increase user's song count
db.run_in_transaction(add_mapping, s.key(), 'Awesome', u.key())
# Increase song's user count (non-transactional)
s.user_count += 1
s.put()
的问题是:我怎样才能事务管理两个计数器?
基于我的理解,这将是不可能的,因为用户,歌曲和SongUser必须是相同的entity group的一部分。他们不能在一个实体组中,因为那时我的所有数据都将在一个组中,并且不能由用户分配。
您的解决方案可以减少争用,但我真正想要做的是确保两个计数器都匹配底层'SongUser'记录。如果我使用'Song'实体的分片计数器,那么当创建'SongUser'时仍然可以成功,并且增加歌曲的计数器失败(反之亦然)。 – cope360 2010-02-11 15:09:59
已注意。我更新了我的答案以反映您的担忧。 – 2010-02-11 15:55:43
我认为最后一段中的解决方案可能是GAE限制中的最佳选择。在那个解决方案中,我们翻转了我第一个评论的例子。例如,现在可以更新/创建乐曲计数器和SongUser记录,但用户记录更新失败(反之亦然)。你是否同意不可能更新两个计数器(分片还是不分片)? – cope360 2010-02-11 17:34:44