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