GAE Entity group / моделирование данных для согласованности и производительности

Как продолжениев этом постеЭто вопрос в стиле замкового камня, чтобы укрепить мое пониманиеGAE-хранилищу и получить некоторые критические замечания о моих решениях моделирования данных. Я изменю пример Jukebox, созданный @Jimmy Kane, чтобы лучше отразить мой реальный пример.

В исходной настройке

Представьте, что у вас есть музыкальный автомат с очередями на комнату, скажем. И люди ставят песни в очередь в каждую очередь каждого музыкального автомата.

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 песни в любую очередь. Во внешнем интерфейсе пользователи посещают пользовательский интерфейс, чтобы увидеть свои песни в каждой из очередей и внести изменения. В серверной части приложение должно знать, какие песни находятся в каждой очереди, воспроизводить правильную песню из каждой очереди и удалять песни из очередей после их воспроизведения.

Чтобы пользователь мог видеть свои песни в очереди, я предполагаю, что каждый пользователь будет корневым объектом и должен будет хранить список ключей песен.

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)

И с тех порgetстрого согласуются, пользователь всегда будет видеть не устаревшие данные

Затем, когда очередь 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 группа объектов?Я не ожидал бы, что это будет вариант использования с высокой пропускной способностью, но мой реальный сценарий должен масштабироваться с количеством пользователей, и, вероятно, такое же количествоqueueс как естьuserс, может быть 2x - 5x большеuserс чемqueues. Если вся группа ограничена 1 записью в секунду и множество пользователей, а также каждая очередь могут создавать и обновлять песни, это может стать узким местомОдним из решений может быть избавление отJukebox корневая сущность и каждыйQueue быть его собственной корневой сущностьюUser.song_keys может быть долго, скажем, 100song.keys.эта статья посоветовал «избегать хранения чрезмерно больших списков ключей в ListProperty». В чем здесь проблема? Является ли это концепцией БД и спорным способом обработки списков с помощьюrepeated=True вариант собственности?

Мнения об этом подходе или критические замечания о вещах, которые я в корне не понимаю?

Предположительно, я мог бы также альтернативно, просто симметрично перевернуть модели данных и иметь группы сущностей, которые выглядят какUser ->Song и хранитьsong_keys списки вQueue модель

Ответы на вопрос(2)

Ваш ответ на вопрос