MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Meteor Publish / Subscribe verstehen

Sammlungen, Veröffentlichungen und Abonnements sind ein heikler Bereich von Meteor, den die Dokumentation ausführlicher behandeln könnte, um häufige Verwirrung zu vermeiden, die manchmal durch verwirrende Terminologie verstärkt wird.

Hier erklärt Sacha Greif (Co-Autor von DiscoverMeteor) Veröffentlichungen und Abonnements auf einer Folie:

Um richtig zu verstehen, warum Sie find() aufrufen müssen Mehr als einmal müssen Sie verstehen, wie Sammlungen, Veröffentlichungen und Abonnements in Meteor funktionieren:

  1. Sie definieren Sammlungen in MongoDB. Noch kein Meteor beteiligt. Diese Sammlungen enthalten Datenbankeinträge (von Mongo und Meteor auch „Dokumente“ genannt, aber ein „Dokument“ ist allgemeiner als ein Datenbankeintrag; zum Beispiel sind eine Aktualisierungsspezifikation oder ein Abfrageselektor ebenfalls Dokumente – JavaScript-Objekte, die field: value Paare).

  2. Dann definieren Sie Sammlungen auf dem Meteor-Server mit

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

    Diese Sammlungen enthalten alle die Daten aus den MongoDB-Sammlungen, und Sie können MyCollection.find({...}) ausführen auf ihnen, was einen Cursor zurückgibt (ein Satz von Datensätzen mit Methoden, um sie zu durchlaufen und zurückzugeben).

  3. Dieser Cursor wird (meistens) zum Veröffentlichen verwendet (senden) Sie eine Reihe von Datensätzen (als "Datensatz" bezeichnet). ). Optional können Sie nur einige veröffentlichen Felder aus diesen Datensätzen. Es handelt sich um Datensätze (nicht Sammlungen), die Kunden abonnieren zu. Die Veröffentlichung erfolgt durch eine Veröffentlichungsfunktion, die jedes Mal aufgerufen wird, wenn sich ein neuer Client anmeldet, und die Parameter annehmen kann, um zu verwalten, welche Datensätze zurückgegeben werden sollen (z. B. eine Benutzer-ID, um nur die Dokumente dieses Benutzers zurückzugeben).

  4. Auf dem Client , haben Sie Minimongo-Sammlungen, die teilweise etwas spiegeln der Datensätze vom Server. „Teilweise“, weil sie möglicherweise nur einige der Felder enthalten, und „einige der Datensätze“, weil Sie normalerweise nur die Datensätze an den Client senden möchten, die er benötigt, um das Laden der Seite zu beschleunigen, und nur die, die er benötigt und Zugriffsberechtigung hat.

    Minimongo ist im Wesentlichen eine nicht persistente In-Memory-Implementierung von Mongo in reinem JavaScript. Er dient als lokaler Cache, der nur die Teilmenge der Datenbank speichert, mit der dieser Client arbeitet. Anfragen auf dem Client (find) werden direkt aus diesem Cache bedient, ohne mit dem Server zu sprechen.

    Diese Minimongo-Sammlungen sind zunächst leer. Sie werden gefüllt von

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

    Anrufe. Beachten Sie, dass der zu abonnierende Parameter kein Sammlungsname ist; es ist der Name eines Datensatzes die der Server beim publish verwendet hat Forderung. Das subscribe() call abonniert den Client bei einem Datensatz - eine Teilmenge von Datensätzen aus der Serversammlung (z. B. die letzten 100 Blogbeiträge), mit allen oder einer Teilmenge der Felder in jedem Datensatz (z. B. nur title und date ). Woher weiß Minimongo, in welche Sammlung die eingehenden Aufzeichnungen platziert werden sollen? Der Name der Sammlung ist collection Argument, das im added des Publish-Handlers verwendet wird , changed , und removed Callbacks, oder wenn diese fehlen (was meistens der Fall ist), wird es der Name der MongoDB-Sammlung auf dem Server sein.

Datensätze ändern

Hier macht Meteor es sehr bequem:Wenn Sie einen Datensatz (Dokument) in der Minimongo-Sammlung auf dem Client ändern, aktualisiert Meteor sofort alle davon abhängigen Vorlagen und sendet die Änderungen auch an den Server zurück, der wiederum speichert die Änderungen in MongoDB und sendet sie an die entsprechenden Clients, die einen Datensatz mit diesem Dokument abonniert haben. Dies wird als Latenzkompensation bezeichnet und ist eines der sieben Grundprinzipien von Meteor.

Mehrere Abonnements

Sie können eine Reihe von Abonnements haben, die unterschiedliche Datensätze abrufen, aber sie landen alle in derselben Sammlung auf dem Client, wenn sie basierend auf ihrer _id aus derselben Sammlung auf dem Server stammen . Dies wird nicht klar erklärt, aber von den Meteor-Dokumenten impliziert:

Wenn Sie einen Datensatz abonnieren, wird der Server angewiesen, Datensätze an den Client zu senden. Der Client speichert diese Datensätze in lokalen Minimongo-Sammlungen mit demselben Namen wie die collection Argument, das im added des Publish-Handlers verwendet wird , changed , und removed Rückrufe. Meteor stellt eingehende Attribute in eine Warteschlange, bis Sie die Mongo.Collection auf dem Client mit dem passenden Sammlungsnamen deklarieren.

Was nicht erklärt wird, ist, was passiert, wenn Sie es nicht tun Verwenden Sie explizit added , changed und removed , oder überhaupt Handler veröffentlichen - was meistens der Fall ist. In diesem häufigsten Fall wird das Sammlungsargument (wenig überraschend) aus dem Namen der MongoDB-Sammlung entnommen, die Sie in Schritt 1 auf dem Server deklariert haben Datensätze landen in derselben Sammlung auf dem Client. Bis zur Ebene der Felder der obersten Ebene , sorgt Meteor dafür, eine festgelegte Vereinigung zwischen Dokumenten durchzuführen, so dass sich Abonnements überlappen können - veröffentlichen Sie Funktionen, die verschiedene Felder der obersten Ebene nebeneinander an den Client senden, und auf dem Client wird das Dokument in der Sammlung die Vereinigung der beiden sein Gruppen von Feldern.

Beispiel:Mehrere Abonnements füllen dieselbe Sammlung auf dem Client

Sie haben eine BlogPosts-Sammlung, die Sie sowohl auf dem Server als auch auf dem Client auf die gleiche Weise deklarieren, obwohl sie unterschiedliche Dinge tut:

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

Auf dem Client BlogPosts kann Aufzeichnungen erhalten von:

  1. ein Abonnement für die letzten 10 Blogbeiträge

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    
  2. ein Abonnement für die Beiträge des aktuellen Benutzers

    // 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. ein Abonnement für die beliebtesten Beiträge

  4. usw.

Alle diese Dokumente stammen aus den posts Sammlung in MongoDB, über die BlogPosts Sammlung auf dem Server und landen in den BlogPosts Sammlung auf dem Client.

Jetzt können wir verstehen, warum Sie find() aufrufen müssen mehr als einmal - beim zweiten Mal auf dem Client, da Dokumente aus allen Abonnements in derselben Sammlung landen und Sie nur die abrufen müssen, die Ihnen wichtig sind. Um beispielsweise die neuesten Posts auf dem Client zu erhalten, spiegeln Sie einfach die Abfrage vom Server:

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

Dadurch wird ein Cursor zu allen Dokumenten/Aufzeichnungen zurückgegeben, die der Client bisher erhalten hat, sowohl zu den Top-Beiträgen als auch zu den Beiträgen des Benutzers. (danke Geoffrey).