GAE Entity group / modelowanie danych dla spójności i wydajności
Jako kontynuacjaw tym poście, to jest pytanie o stylu zwieńczenia, aby umocnić moje zrozumieniegae-datastore i zdobądź krytykę moich decyzji dotyczących modelowania danych. Zmodyfikuję przykład Jukebox stworzony przez @Jimmy Kane, aby lepiej odzwierciedlał mój prawdziwy świat.
W oryginalnej konfiguracji
wyobraź sobie, że masz szafę grającą z kolejkami na pokój, powiedzmy. Ludzie kolejkują utwory do każdej kolejki każdej szafy grającej.
J=Jukebox, Q=queue, S=Song
Jukebox
/ | \
Q1 Q2 Q3
/ | \ | \
S1 S2 S3 S4 S5
Najpierw wypełnij model piosenki jako taki:
Song(ndb.Model):
user_key = ndb.KeyProperty()
status = ndb.StringProperty()
datetime_added = ndb.DateTimeProperty()
Moja modyfikacja polega na dodaniuUser
które mogą CUD piosenki do dowolnej kolejki. W interfejsie użytkownicy odwiedzą interfejs użytkownika, aby zobaczyć ich piosenki w każdej kolejce i wprowadzić zmiany. W backendie aplikacja musi wiedzieć, które utwory znajdują się w każdej kolejce, odtwarzać odpowiednią piosenkę z każdej kolejki i usuwać utwory z kolejek po ich odtworzeniu.
Aby użytkownik mógł zobaczyć swoje utwory w kolejce, zakładam, że każdy użytkownik byłby podmiotem głównym i musiałby przechowywać listę kluczy utworów
User(ndb.Model):
song_keys = ndb.KeyProperty(kind='Song', repeated=True)
Następnie, aby pobrać utwory użytkownika, aplikacja wykona (zakładając, że user_id jest znany)
user = User.get_by_id(user_id)
songs = ndb.get_multi(user.song_keys)
I od tego czasuget
s są silnie spójne, użytkownik zawsze będzie widział nieświeże dane
Następnie, gdy kolejka 1 zakończy odtwarzanie utworu, aplikacja może zrobić coś takiego:
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()
Czy mam rację, sądząc, że zapytanie przodków zapewnia spójną reprezentację poprzedniej dezaktywacji bieżącej piosenki, a także każdego CUD od użytkowników?
Ostatnim krokiem byłoby zaktualizowanie listy kluczy użytkownika w transakcji
user = current_song.user_key.get()
user.song_keys.remove(current_song.key)
user.put()
Podsumowanie i niektóre zalety / wady
Wydaje się, że konsekwencja jest właściwa, jeśli moje rozumienie jest słuszne?Czy powinienem się martwić o spór na tematJukebox
grupa podmiotów?Nie spodziewałbym się, że będzie to przypadek użycia o dużej przepustowości, ale mój rzeczywisty scenariusz wymaga skalowania z liczbą użytkowników i prawdopodobnie jest podobna liczbaqueue
s, jak sąuser
s, może 2x - 5x więcejuser
s niżqueue
s. Jeśli cała grupa jest ograniczona do 1 zapisu / s, a wielu użytkowników i każda kolejka może tworzyć i aktualizować utwory, może to być wąskie gardłoJednym z rozwiązań może być rezygnacja zJukebox
root root i mieć każdyQueue
być jego własnym korzeniemUser.song_keys
może być długa, powiedzmy 100song.key
s.Ten artykuł radzono „unikać przechowywania zbyt dużych list kluczy w obiekcie ListProperty”. O co tu chodzi? Czy jest to koncepcja db i moot ze sposobem obsługi list przez ndb za pomocąrepeated=True
opcja nieruchomości?Opinie na temat tego podejścia lub krytyki rzeczy, których zasadniczo nie rozumiem?
Przypuszczalnie mogłem też, alternatywnie, po prostu symetrycznie odwracać modele danych i wyglądać jak grupy jednostekUser
->Song
i przechowujsong_keys
listy wQueue
Model