How to count both sides of a many-to-many relationship in Google App Engine

Consider the GAE (python) application, which allows users to comment on songs. The expected number of users is 1,000,000+. The expected number of songs is 5,000.

The application should be able to:

  • Indicate the number of songs the user has commented on.
  • Indicate the number of users who commented on the song

Counter management must be transactional so that they always display baseline data.

It seems that GAE applications should constantly calculate these types of counts, as requesting them during the request will be ineffective.

My data model

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)

code
This handles the number of user songs in a transaction, but not the number of users of a song.

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 song count
db.run_in_transaction(add_mapping, s.key(), 'Awesome', u.key())

# Increase song user count (non-transactional)
s.user_count += 1
s.put()

: ?

, , , SongUser . , .

+3
1

, , , , , ?

, , , , .

, , Song, , , .

Sharded Counters.

, SongUser , , SongUser Song . , SongUser . SongUser ReferenceProperty.

( ), , , , , , , . : . TransactionfailedError, - .

, , . , . - , , , , . , , AppEngine .

: , , - , ? , ?

+1

Source: https://habr.com/ru/post/1732352/


All Articles