ten jest kopiowany z mojej odpowiedzi na zobiektywizować-interfejsu App Engine grupy dyskusyjne: https://groups.google.com/forum/?fromgroups#!topic/objectify-appengine/LlOyRJZRbnk
Istnieją trzy główne opcje gdy mamy do czynienia z „danych agregacji” jak to, co można opisać:
1) Oblicz ją, kiedy jej potrzebujesz
Uznałeś, słusznie, że jest to zbyt kosztowne.
2) Oblicz go w odstępach wsadowych i przechowywać ten wynik
Nie bardzo satysfakcjonujące, gdyż wiąże się z opóźnieniem. Poza tym nie chcesz codziennie przeczesywać całej bazy danych.
3) Aktualizacja agregację gdy dane zmienia
Takie podejście wymaga trochę więcej pracy przy każdej zmianie danych, ale jest to prawie na pewno to, co chcesz robić.
Utwórz kolekcję kontaktów dla każdego użytkownika. Po nadejściu wiadomości upewnij się, że kontakt nadawcy istnieje dla tego odbiorcy. Może chcesz również usunąć kontakt, gdy odbiorca usunie ostatnią wiadomość od nadawcy.
Należy uważać, aby nie przekroczyć limitów transakcji dla grup jednostek (jeden zapis na sekundę).Odprowadzę cię przez kilka opcji:
1) mógłby przechowywać listę kontaktów w każdej odbiorcy:
class Person {
@Id Long id;
Set<Key<Person>> contacts;
}
Byłby to wyraźny problem, jeśli, powiedzmy, odbiorca otrzymał wiadomość od 20 nowy ludzie naraz. To prawie na pewno zły pomysł. Z drugiej strony jest niesamowicie szybki i skuteczny, aby sprawdzić, kim są twoje kontakty. Niewielka poprawa byłoby przenieść to do odrębnego podmiotu wychowywane przez osobę, więc nie zawsze ładuje te dane:
class Contacts {
@Parent Key<Person> owner;
@Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching
Set<Key<Person>> contacts;
}
Oczywiście, mieszczący się w jedną całość daje limit 50.000 wejścia. Może być nieco mniejsza niż ta, jeśli najpierw przekroczysz limit wielkości jednostki 1M. Jeśli twoje klucze mają ~ 20 znaków, będzie mniej więcej tak samo. Jeśli jest to problem, możesz zezwolić na wiele jednostek Kontakty, w którym to momencie masz coś podobnego do Wzorca Podmiotu Relacji z Bretta Slatkina z Google 2009: http://www.youtube.com/watch?v=AgaL6NGpkB8
2) Możesz zapisać listę kontaktów w innym kierunku
class Person {
@Id Long id;
@Index Set<Key<Peson>> contactOf;
}
to sprawia, że jest to nieco droższe, aby dowiedzieć się, kto kontakty są - trzeba tylko klucze zapytania, a nie klucza get-by-proste. Ale nie jesteś tak naprawdę ograniczony stopniem zapisu jednostki. Ludzie prawdopodobnie nie wysyłają więcej niż jednej wiadomości na sekundę, a jeśli wysyłają masowo 1000 wiadomości, można zaktualizować dane kontaktowe w pojedynczej transakcji.
Jak wyżej, prawdopodobnie chcesz przenieść ten wskaźnik do odrębnego podmiotu:
class Contacts {
@Parent Key<Person> person;
@Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching
Set<Key<Person>> of;
}
3) Można również zapisać te kontakty w zupełnie odrębny podmiot
class Contact {
@Parent Key<Person> person;
@Id Long id;
@Index Key<Person> owner;
}
To jest naprawdę mniej wydajny pod względem przestrzeni sposób rozwiązania # 2.
Ważne jest, aby aktualizować tę strukturę, gdy wszystkie wiadomości są wysyłane lub odbierane.
Dziękujemy za kompleksową odpowiedź. Zadaję pytania uzupełniające w grupie google-appengine. – spierce7
Jest to limit 5 000, a nie 50 000 - prawdopodobnie literówka. – gswierczynski