sql >> Databáze >  >> NoSQL >> MongoDB

Porozumění Meteor Publish / Subscribe

Sbírky, publikace a předplatné jsou záludnou oblastí Meteoru, kterou by dokumentace mohla probrat podrobněji, aby se předešlo častým nejasnostem, které jsou někdy umocněny matoucí terminologií.

Zde je Sacha Greif (spoluautor DiscoverMeteor), který vysvětluje publikace a předplatné na jednom snímku:

Abyste správně pochopili, proč musíte volat find() více než jednou, musíte pochopit, jak sbírky, publikace a předplatné fungují v Meteoru:

  1. Kolekce definujete v MongoDB. Zatím není zapojen žádný Meteor. Tyto kolekce obsahují záznamy databáze (Mongem i Meteorem nazývané také „dokumenty“, ale „dokument“ je obecnější než záznam databáze; například specifikace aktualizace nebo selektor dotazu jsou také dokumenty – objekty JavaScript obsahující field:value páry).

  2. Poté definujete kolekce na serveru Meteor s

    MyCollection = new Mongo.Collection('collection-name-in-mongo')
    

    Tyto kolekce obsahují vše data z kolekcí MongoDB a můžete spustit MyCollection.find({...}) na ně, což vrátí kurzor (soubor záznamů s metodami, jak je procházet a vracet).

  3. Tento kurzor se (většinou) používá k publikování (odeslat) sadu záznamů (nazývanou "sada záznamů" ). Volitelně můžete publikovat pouze některé pole z těchto záznamů. Jde o sady záznamů (ne kolekce), které si klienti přihlásí na. Publikování se provádí pomocí funkce publikování, která je volána pokaždé, když se nový klient přihlásí k odběru, a která může mít parametry pro správu, které záznamy se mají vrátit (např. ID uživatele, chcete-li vrátit pouze dokumenty tohoto uživatele).

  4. U klienta , máte kolekce Minimongo, které částečně zrcadlit některé záznamů ze serveru. „Částečně“, protože mohou obsahovat jen některá z polí, a „některé ze záznamů“, protože obvykle chcete klientovi poslat jen ty záznamy, které potřebuje, pro urychlení načítání stránky a jen ty, které potřebujea má oprávnění k přístupu.

    Minimongo je v podstatě neperzistentní implementace Mongo v čistém JavaScriptu v paměti. Slouží jako lokální mezipaměť, která ukládá pouze podmnožinu databáze, se kterou tento klient pracuje. Dotazy na klienta (najít) jsou obsluhovány přímo z této mezipaměti, bez komunikace se serverem.

    Tyto kolekce Minimongo jsou zpočátku prázdné. Jsou vyplněny

    Meteor.subscribe('record-set-name')
    

    hovory. Všimněte si, že parametr pro přihlášení není název kolekce; je to název sady záznamů které server použil při publikovat volání. subscribe() hovor přihlásí klienta k odběru sady záznamů – podmnožina záznamů z kolekce serveru (např. posledních 100 blogových příspěvků), se všemi nebo podmnožinou polí v každém záznamu (např. pouze title a datum ). Jak Minimongo ví, do které sbírky má umístit příchozí záznamy? Název kolekce bude kolekce argument použitý v obslužné rutině publikování přidáno , změněno a odstraněno zpětná volání, nebo pokud tato chybí (což je většinou případ), bude to název kolekce MongoDB na serveru.

Úprava záznamů

Zde je Meteor velmi pohodlný:když upravíte záznam (dokument) v kolekci Minimongo na klientovi, Meteor okamžitě aktualizuje všechny šablony, které na něm závisí, a také odešle změny zpět na server, který zase uloží změny v MongoDB a odešle je příslušným klientům, kteří si předplatili sadu záznamů obsahující daný dokument. Říká se tomu kompenzace latence a je jedním ze sedmi základních principů Meteoru.

Více odběrů

Můžete mít spoustu předplatných, která stahují různé záznamy, ale všechna skončí ve stejné sbírce na klientovi, pokud pocházejí ze stejné kolekce na serveru na základě jejich _id . To není jasně vysvětleno, ale vyplývá z Meteor docs:

Když se přihlásíte k odběru sady záznamů, sdělí to serveru, aby poslal záznamy klientovi. Klient ukládá tyto záznamy do místních kolekcí Minimongo se stejným názvem jako kolekce argument použitý v obslužné rutině publikování přidáno , změněno a odstraněno zpětná volání. Meteor bude řadit příchozí atributy do fronty, dokud nedeklarujete Mongo.Collection na klientovi s odpovídajícím názvem kolekce.

Není vysvětleno, co se stane, když to neděláte explicitně použijte přidáno , změněno a odstraněno , nebo vůbec publikovat handlery – což je většinou. V tomto nejběžnějším případě je argument kolekce (nepřekvapivě) převzat z názvu kolekce MongoDB, kterou jste deklarovali na serveru v kroku 1. To však znamená, že můžete mít různé publikace a předplatná s různými názvy a všechny záznamy skončí ve stejné kolekci na klientovi. Až na úroveň polí nejvyšší úrovně , Meteor se stará o provedení sady mezi dokumenty, takže se předplatná mohou překrývat - publikovat funkce, které doručují různá pole nejvyšší úrovně do klientské práce vedle sebe a na klientovi, dokument v kolekci bude spojením těchto dvou sady polí.

Příklad:více předplatných vyplňujících stejnou sbírku na klientovi

Máte sbírku BlogPosts, kterou deklarujete stejným způsobem na serveru i na klientovi, i když dělá různé věci:

BlogPosts = new Mongo.Collection('posts');

Na klientovi BlogPosts můžete získat záznamy z:

  1. přihlášení k odběru posledních 10 blogových příspěvků

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    
  2. přihlášení k odběru příspěvků aktuálního uživatele

    // 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 - http://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);
    
  3. předplatné nejoblíbenějších příspěvků

  4. atd.

Všechny tyto dokumenty pocházejí z příspěvků sběr v MongoDB prostřednictvím BlogPosts kolekce na serveru a skončí v BlogPosts inkaso na klientovi.

Nyní chápeme, proč potřebujete volat find() více než jednou – podruhé na klientovi, protože dokumenty ze všech předplatných skončí ve stejné sbírce a vy musíte načíst pouze ty, na kterých vám záleží. Chcete-li například získat nejnovější příspěvky na klientovi, jednoduše zrcadlíte dotaz ze serveru:

var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});

Tím se vrátí kurzor na všechny dokumenty/záznamy, které klient dosud obdržel, a to jak horní příspěvky, tak příspěvky uživatele. (díky Geoffreymu).



  1. Která databáze noSQL je nejlepší pro velkoobjemové vkládání/zápisy?

  2. docker:MISCONF Redis je nakonfigurován pro ukládání snímků RDB

  3. Aplikace podobná Twitteru využívající MongoDB

  4. Jak získat klíč z hodnoty v páru klíč/hodnota v klientovi úložiště redis?