MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Comprensione di Meteor Pubblica/Abbonati

Raccolte, pubblicazioni e abbonamenti sono un'area delicata di Meteor, che la documentazione potrebbe discutere in modo più dettagliato, in modo da evitare frequenti confusioni, che a volte vengono amplificate da terminologia confusa.

Ecco Sacha Greif (coautore di DiscoverMeteor) che spiega pubblicazioni e abbonamenti in una diapositiva:

Per capire correttamente perché devi chiamare find() più di una volta, devi capire come funzionano raccolte, pubblicazioni e abbonamenti in Meteor:

  1. Definisci le raccolte in MongoDB. Nessun Meteor ancora coinvolto. Queste raccolte contengono record di database (chiamato anche "documenti" sia da Mongo che da Meteor, ma un "documento" è più generale di un record di database; ad esempio, anche una specifica di aggiornamento o un selettore di query sono documenti - oggetti JavaScript contenenti field: value coppie).

  2. Quindi definisci le raccolte sul server Meteor con

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

    Queste raccolte contengono tutte i dati dalle raccolte MongoDB e puoi eseguire MyCollection.find({...}) su di essi, che restituirà un cursore (un insieme di record, con metodi per scorrere e restituirli).

  3. Questo cursore viene utilizzato (il più delle volte) per pubblicare (inviare) un set di record (denominato "set di record" ). Facoltativamente, puoi pubblicarne solo alcuni campi da quei record. Sono set di record (non raccolte) che i clienti sottoscrivono a. La pubblicazione avviene tramite una funzione di pubblicazione, che viene richiamata ogni volta che un nuovo cliente si iscrive e che può assumere parametri per gestire quali record restituire (ad esempio un ID utente, per restituire solo i documenti di quell'utente).

  4. Sul cliente , hai collezioni Minimongo che parzialmente rispecchia alcuni dei record dal server. "Parzialmente" perché possono contenere solo alcuni dei campi, e "alcuni dei record" perché di solito si desidera inviare al cliente solo i record di cui ha bisogno, per velocizzare il caricamento della pagina, e solo quelli di cui ha bisogno e ha il permesso di accedere.

    Minimongo è essenzialmente un'implementazione in memoria e non persistente di Mongo in puro JavaScript. Funge da cache locale che memorizza solo il sottoinsieme del database con cui sta lavorando questo client. Le query sul client (find) vengono servite direttamente da questa cache, senza parlare con il server.

    Queste raccolte Minimongo sono inizialmente vuote. Sono riempiti da

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

    chiamate. Si noti che il parametro da sottoscrivere non è un nome di raccolta; è il nome di un set di record che il server ha utilizzato nella publish chiamata. Il subscribe() call iscrive il client a un set di record - un sottoinsieme di record dalla raccolta del server (ad es. i 100 post del blog più recenti), con tutti o un sottoinsieme dei campi in ciascun record (ad es. solo title e date ). Come fa Minimongo a sapere in quale collezione inserire i record in entrata? Il nome della collezione sarà collection argomento utilizzato nel added del gestore di pubblicazione , changed e removed callback o, se mancano (come accade la maggior parte delle volte), sarà il nome della raccolta MongoDB sul server.

Modifica dei record

È qui che Meteor rende le cose molto convenienti:quando modifichi un record (documento) nella raccolta Minimongo sul client, Meteor aggiornerà istantaneamente tutti i modelli che dipendono da esso e invierà anche le modifiche al server, che a sua volta memorizzerà le modifiche in MongoDB e le invierà ai client appropriati che hanno sottoscritto un set di record che include quel documento. Questo è chiamato compensazione della latenza ed è uno dei sette principi fondamentali di Meteor.

Abbonamenti multipli

Puoi avere un sacco di abbonamenti che estraggono record diversi, ma finiranno tutti nella stessa raccolta sul client se provengono dalla stessa raccolta sul server, in base al loro _id . Questo non è spiegato chiaramente, ma è implicito nei documenti di Meteor:

Quando ti iscrivi a un set di record, indica al server di inviare record al client. Il client archivia questi record nelle raccolte Minimongo locali, con lo stesso nome della collection argomento utilizzato nel added del gestore di pubblicazione , changed e removed richiamate. Meteor metterà in coda gli attributi in entrata finché non dichiarerai Mongo.Collection sul client con il nome della raccolta corrispondente.

Ciò che non viene spiegato è cosa succede quando non usa esplicitamente added , changed e removed o pubblicare gestori del tutto, che è la maggior parte delle volte. In questo caso più comune, l'argomento della raccolta è (non sorprendentemente) preso dal nome della raccolta MongoDB che hai dichiarato sul server al passaggio 1. Ma ciò significa che puoi avere diverse pubblicazioni e sottoscrizioni con nomi diversi e tutte le i record finiranno nella stessa raccolta sul client. Fino al livello dei campi di primo livello , Meteor si occupa di eseguire un'unione prestabilita tra i documenti, in modo tale che gli abbonamenti possano sovrapporsi - pubblicare funzioni che spediscono diversi campi di primo livello al cliente lavorano fianco a fianco e sul cliente, il documento nella raccolta sarà l'unione dei due insiemi di campi.

Esempio:più abbonamenti che riempiono la stessa raccolta sul client

Hai una raccolta BlogPosts, che dichiari allo stesso modo sia sul server che sul client, anche se fa cose diverse:

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

Sul client, BlogPosts può ottenere record da:

  1. un abbonamento ai 10 post più recenti del blog

    // server
    Meteor.publish('posts-recent', function publishFunction() {
      return BlogPosts.find({}, {sort: {date: -1}, limit: 10});
    }
    // client
    Meteor.subscribe('posts-recent');
    
  2. un abbonamento ai post dell'utente corrente

    // 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. un abbonamento ai post più popolari

  4. ecc.

Tutti questi documenti provengono dai posts raccolta in MongoDB, tramite BlogPosts raccolta sul server e finiscono nei BlogPosts ritiro sul cliente.

Ora possiamo capire perché devi chiamare find() più di una volta - la seconda volta sul client, perché i documenti di tutti gli abbonamenti finiranno nella stessa raccolta e devi recuperare solo quelli a cui tieni. Ad esempio, per ottenere i post più recenti sul client, è sufficiente eseguire il mirroring della query dal server:

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

Questo restituirà un cursore su tutti i documenti/record che il cliente ha ricevuto finora, sia i primi post che i post dell'utente. (grazie Geoffrey).