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

Come funziona l'esempio di conteggio dei messaggi nei documenti di Meteor?

Grazie per avermi chiesto di scrivere una spiegazione più chiara. Ecco un esempio più completo con i miei commenti. C'erano alcuni bug e incongruenze che ho ripulito. La prossima versione di documenti utilizzerà questo.

Meteor.publish è abbastanza flessibile. Non si limita a pubblicare raccolte MongoDB esistenti sul client:possiamo pubblicare tutto ciò che vogliamo. In particolare, Meteor.publish definisce un insieme di documenti a cui un cliente può iscriversi. Ogni documento appartiene a un nome di raccolta (una stringa), ha un _id univoco campo, e quindi ha una serie di attributi JSON. Man mano che i documenti nel set cambiano, il server invierà le modifiche a ciascun client sottoscritto, mantenendo il client aggiornato.

Definiremo qui un set di documenti, chiamato "counts-by-room" , che contiene un singolo documento in una raccolta denominata "counts" . Il documento avrà due campi:un roomId con l'ID di una stanza e count :il numero totale di messaggi in quella stanza. Non esiste una vera raccolta MongoDB denominata counts . Questo è solo il nome della raccolta che il nostro server Meteor invierà al client e memorizzerà in un lato client raccolta denominata counts .

Per fare ciò, la nostra funzione di pubblicazione accetta un roomId parametro che verrà dal client e osserva una query di tutti i messaggi (definiti altrove) in quella stanza. Possiamo usare il più efficiente observeChanges forma di osservazione di una query qui poiché non avremo bisogno del documento completo, ma solo della conoscenza che ne è stato aggiunto o rimosso uno nuovo. Ogni volta che viene aggiunto un nuovo messaggio con roomId siamo interessati, la nostra richiamata incrementa il conteggio interno e quindi pubblica un nuovo documento per il cliente con quel totale aggiornato. E quando un messaggio viene rimosso, diminuisce il conteggio e invia al client l'aggiornamento.

Quando chiamiamo per la prima volta observeChanges , un certo numero di added le richiamate verranno eseguite immediatamente, per ogni messaggio già esistente. Quindi le modifiche future verranno attivate ogni volta che i messaggi vengono aggiunti o rimossi.

La nostra funzione di pubblicazione registra anche un onStop gestore per ripulire quando il client annulla l'iscrizione (manualmente o alla disconnessione). Questo gestore rimuove gli attributi dal client e interrompe l'esecuzione di observeChanges .

Una funzione di pubblicazione viene eseguita ogni volta che un nuovo client si iscrive a "counts-by-room" , quindi ogni client avrà un observeChanges in esecuzione per suo conto.

// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
  var self = this;
  var count = 0;
  var initializing = true;

  var handle = Messages.find({room_id: roomId}).observeChanges({
    added: function (doc, idx) {
      count++;
      if (!initializing)
        self.changed("counts", roomId, {count: count});  // "counts" is the published collection name
    },
    removed: function (doc, idx) {
      count--;
      self.changed("counts", roomId, {count: count});  // same published collection, "counts"
    }
    // don't care about moved or changed
  });

  initializing = false;

  // publish the initial count. `observeChanges` guaranteed not to return
  // until the initial set of `added` callbacks have run, so the `count`
  // variable is up to date.
  self.added("counts", roomId, {count: count});

  // and signal that the initial document set is now available on the client
  self.ready();

  // turn off observe when client unsubscribes
  self.onStop(function () {
    handle.stop();
  });
});

Ora, sul client, possiamo trattarlo proprio come un tipico abbonamento Meteor. Innanzitutto, abbiamo bisogno di una Mongo.Collection che conterrà il nostro documento di conteggi calcolati. Poiché il server sta pubblicando in una raccolta denominata "counts" , passiamo "counts" come argomento per Mongo.Collection costruttore.

// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");

Allora possiamo iscriverci. (Puoi effettivamente iscriverti prima di dichiarare la raccolta:Meteor metterà in coda gli aggiornamenti in arrivo finché non ci sarà un posto dove metterli.) Il nome dell'abbonamento è "counts-by-room" , e richiede un argomento:l'ID della stanza corrente. L'ho inserito in Deps.autorun in modo che come Session.get('roomId') modifiche, il cliente annullerà automaticamente l'iscrizione al conteggio della vecchia stanza e si riabbonerà al conteggio della nuova stanza.

// client: autosubscribe to the count for the current room
Tracker.autorun(function () {
  Meteor.subscribe("counts-by-room", Session.get("roomId"));
});

Infine, abbiamo il documento in Counts e possiamo usarlo proprio come qualsiasi altra collezione Mongo sul client. Qualsiasi modello che fa riferimento a questi dati verrà automaticamente ridisegnato ogni volta che il server invia un nuovo conteggio.

// client: use the new collection
console.log("Current room has " + Counts.findOne().count + " messages.");