考虑一个允许用户评论歌曲的 GAE (python) 应用程序。预期用户数为 1,000,000+。预计歌曲数量为 5,000 首。
该应用程序必须能够:
- 给出用户评论过的歌曲数量
- 给出对歌曲发表评论的用户数
柜台管理必须是事务性的,以便它们始终反映基础数据。
似乎 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='me@example.com')
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()
问题是: 如何以事务方式管理这两个计数器?
根据我的理解,这是不可能的,因为 User、Song 和 SongUser 必须属于同一个实体组。他们不能在一个实体组中,因为这样我的所有数据都将在一个组中,并且不能由用户分发。