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 czasugets 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 liczbaqueues, jak sąusers, może 2x - 5x więcejusers niżqueues. 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.keys.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

questionAnswers(2)

yourAnswerToTheQuestion