Kolekcje, publikacje i subskrypcje to trudny obszar Meteoru, który dokumentacja mogłaby omówić bardziej szczegółowo, aby uniknąć częstych nieporozumień, które czasami są wzmacniane przez mylącą terminologię.
Oto Sacha Greif (współautorka DiscoverMeteor) wyjaśniająca publikacje i subskrypcje na jednym slajdzie:

Aby właściwie zrozumieć, dlaczego musisz wywołać find() więcej niż raz, musisz zrozumieć, jak działają kolekcje, publikacje i subskrypcje w Meteor:
-
Kolekcje definiujesz w MongoDB. Nie ma jeszcze Meteora. Te kolekcje zawierają rekordy bazy danych (nazywane również „dokumentami” zarówno przez Mongo, jak i Meteor, ale „dokument” jest bardziej ogólny niż rekord bazy danych; na przykład specyfikacja aktualizacji lub selektor zapytania również są dokumentami – obiekty JavaScript zawierające
pole:wartość par). -
Następnie definiujesz kolekcje na serwerze Meteor z
MyCollection = new Mongo.Collection('collection-name-in-mongo')Te kolekcje zawierają wszystkie dane z kolekcji MongoDB i możesz uruchomić
MyCollection.find({...})na nich, co zwróci kursor (zestaw rekordów wraz z metodami ich iteracji i zwracania). -
Ten kursor jest (przez większość czasu) używany do publikowania (wyślij) zestaw rekordów (zwany "zestawem rekordów" ). Opcjonalnie możesz opublikować tylko niektóre pola z tych rekordów. To zestawy rekordów (nie kolekcje), które klienci subskrybują do. Publikowanie odbywa się za pomocą funkcji publikowania, która jest wywoływana za każdym razem, gdy subskrybuje nowy klient i która może przyjmować parametry do zarządzania rekordami do zwrócenia (np. identyfikator użytkownika, aby zwrócić tylko dokumenty tego użytkownika).
-
Na kliencie , masz kolekcje Minimongo, które częściowo lustro niektóre rekordów z serwera. "Częściowo", ponieważ mogą zawierać tylko niektóre pola, i "niektóre z rekordów", ponieważ zazwyczaj chcesz wysłać do klienta tylko te rekordy, których potrzebuje, aby przyspieszyć ładowanie strony i tylko te, których potrzebuje i ma pozwolenie na dostęp.
Minimongo jest zasadniczo nietrwałą implementacją Mongo w pamięci w czystym JavaScript. Służy jako lokalna pamięć podręczna, która przechowuje tylko podzbiór bazy danych, z którą pracuje ten klient. Zapytania na kliencie (znajdź) są obsługiwane bezpośrednio z tej pamięci podręcznej, bez komunikowania się z serwerem.
Te kolekcje Minimongo są początkowo puste. Wypełnia je
Meteor.subscribe('record-set-name')wzywa. Zauważ, że parametr do zasubskrybowania nie jest nazwą kolekcji; to nazwa zestawu rekordów serwer używany w
opublikowaniupołączenie.subscribe()wywołanie subskrybuje klienta do zestawu rekordów - podzbiór rekordów z kolekcji serwera (np. 100 ostatnich postów na blogu), ze wszystkimi lub podzbiorem pól w każdym rekordzie (np. tylkotytułidata). Skąd Minimongo wie, w której kolekcji umieścić przychodzące rekordy? Nazwą kolekcji będziekolekcjaargument używany waddedprocedury obsługi publikowania ,zmienionoiusuniętywywołania zwrotne, lub jeśli ich brakuje (co ma miejsce w większości przypadków), będzie to nazwa kolekcji MongoDB na serwerze.
Modyfikowanie rekordów
W tym miejscu Meteor sprawia, że wszystko jest bardzo wygodne:kiedy zmodyfikujesz rekord (dokument) w kolekcji Minimongo na kliencie, Meteor natychmiast zaktualizuje wszystkie szablony, które od niego zależą, a także odeśle zmiany z powrotem na serwer, który z kolei zapisze zmiany w MongoDB i wyśle je do odpowiednich klientów, którzy zasubskrybowali zestaw rekordów zawierający ten dokument. Nazywa się to kompensacją opóźnień i jest jedną z siedmiu podstawowych zasad Meteoru.
Wiele subskrypcji
Możesz mieć kilka subskrypcji, które pobierają różne rekordy, ale wszystkie trafią do tej samej kolekcji na kliencie, jeśli pochodzą z tej samej kolekcji na serwerze, na podstawie ich _id . Nie jest to jasno wyjaśnione, ale sugerowane w dokumentacji Meteor:
Kiedy subskrybujesz zestaw rekordów, nakazuje serwerowi wysłanie rekordów do klienta. Klient przechowuje te rekordy w lokalnych kolekcjach Minimongo o tej samej nazwie co kolekcja argument używany w added procedury obsługi publikowania , zmieniono i usunięty wywołania zwrotne. Meteor będzie kolejkować przychodzące atrybuty, dopóki nie zadeklarujesz Mongo.Collection na kliencie z pasującą nazwą kolekcji.
Nie wyjaśniono, co się dzieje, gdy nie jawnie użyj dodano , zmieniono i usunięty , lub w ogóle publikuj programy obsługi — co jest w większości przypadków. W tym najczęstszym przypadku argument kolekcji jest (nie dziwi) wzięty z nazwy kolekcji MongoDB, którą zadeklarowałeś na serwerze w kroku 1. Oznacza to jednak, że możesz mieć różne publikacje i subskrypcje o różnych nazwach, a wszystkie rekordy znajdą się w tej samej kolekcji na kliencie. Aż do poziomu pól najwyższego poziomu , Meteor dba o wykonanie ustalonej unii między dokumentami, tak aby subskrypcje mogły się nakładać - publikuj funkcje, które wysyłają różne pola najwyższego poziomu do klienta, pracują obok siebie i na kliencie, dokument w kolekcji będzie unią tych dwóch zestawy pól.
Przykład:wiele subskrypcji wypełnia tę samą kolekcję na kliencie
Masz kolekcję BlogPosts, którą deklarujesz w ten sam sposób zarówno na serwerze, jak i na kliencie, mimo że robi ona różne rzeczy:
BlogPosts = new Mongo.Collection('posts');
Na kliencie BlogPosts można pobrać rekordy z:
-
subskrypcja ostatnich 10 wpisów na blogu
// server Meteor.publish('posts-recent', function publishFunction() { return BlogPosts.find({}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-recent'); -
subskrypcja postów bieżącego użytkownika
// server Meteor.publish('posts-current-user', function publishFunction() { return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10}); // this.userId is provided by Meteor - https://docs.meteor.com/#publish_userId } Meteor.publish('posts-by-user', function publishFunction(who) { return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe('posts-current-user'); Meteor.subscribe('posts-by-user', someUser); -
subskrypcja najpopularniejszych postów
- itd.
Wszystkie te dokumenty pochodzą z postów kolekcja w MongoDB, za pośrednictwem BlogPosts kolekcja na serwerze i trafia do BlogPosts odbiór na kliencie.
Teraz możemy zrozumieć, dlaczego musisz wywołać find() więcej niż raz - drugi raz będąc u klienta, bo dokumenty ze wszystkich abonamentów trafią do tej samej kolekcji, a Ty musisz pobierać tylko te, na których Ci zależy. Na przykład, aby uzyskać najnowsze posty na kliencie, po prostu odzwierciedlasz zapytanie z serwera:
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
Spowoduje to zwrócenie kursora do wszystkich dokumentów/rekordów, które klient otrzymał do tej pory, zarówno najlepszych postów, jak i postów użytkownika. (dzięki Geoffrey).