ユーザーが曲にコメントできる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は同じエンティティグループの一部である必要があるため、これは不可能です。すべてのデータが1つのグループになり、ユーザーが配布できなかったため、1つのエンティティグループに含めることはできません。