sql >> Base de Datos >  >> NoSQL >> MongoDB

¿Cómo funciona el ejemplo de conteo de mensajes en los documentos de Meteor?

Gracias por animarme a escribir una explicación más clara. Aquí hay un ejemplo más completo con mis comentarios. Había algunos errores e inconsistencias que he limpiado. La próxima versión de documentos usará esto.

Meteor.publish es bastante flexible. No se limita a publicar colecciones MongoDB existentes en el cliente:podemos publicar lo que queramos. Específicamente, Meteor.publish define un conjunto de documentos que un cliente puede suscribirse. Cada documento pertenece a algún nombre de colección (una cadena), tiene un _id único y luego tiene un conjunto de atributos JSON. A medida que cambien los documentos en el conjunto, el servidor enviará los cambios a cada cliente suscrito, manteniendo al cliente actualizado.

Vamos a definir un conjunto de documentos aquí, llamado "counts-by-room" , que contiene un solo documento en una colección llamada "counts" . El documento tendrá dos campos:un roomId con el ID de una habitación y count :el número total de mensajes en esa sala. No hay una colección MongoDB real llamada counts . Este es solo el nombre de la colección que nuestro servidor Meteor enviará al cliente y almacenará en un lado del cliente colección llamada counts .

Para hacer esto, nuestra función de publicación toma un roomId parámetro que vendrá del cliente, y observa una consulta de todos los Mensajes (definidos en otro lugar) en esa sala. Podemos usar el observeChanges más eficiente forma de observar una consulta aquí ya que no necesitaremos el documento completo, solo el conocimiento de que se agregó o eliminó uno nuevo. Cada vez que se agrega un nuevo mensaje con el roomId nos interesa, nuestra devolución de llamada incrementa el conteo interno y luego publica un nuevo documento para el cliente con ese total actualizado. Y cuando se elimina un mensaje, disminuye el conteo y envía la actualización al cliente.

Cuando llamamos por primera vez a observeChanges , algún número de added las devoluciones de llamada se ejecutarán de inmediato, para cada mensaje que ya existe. Luego, los cambios futuros se activarán cada vez que se agreguen o eliminen mensajes.

Nuestra función de publicación también registra un onStop controlador para limpiar cuando el cliente se da de baja (ya sea manualmente o al desconectarse). Este controlador elimina los atributos del cliente y elimina los observeChanges en ejecución. .

Una función de publicación se ejecuta cada vez que un nuevo cliente se suscribe a "counts-by-room" , por lo que cada cliente tendrá un observeChanges corriendo en su nombre.

// 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();
  });
});

Ahora, en el cliente, podemos tratar esto como una suscripción típica de Meteor. Primero, necesitamos una Mongo.Collection que contendrá nuestro documento de conteos calculados. Dado que el servidor está publicando en una colección llamada "counts" , pasamos "counts" como argumento para Mongo.Collection constructor.

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

Entonces podemos suscribirnos. (De hecho, puede suscribirse antes de declarar la colección:Meteor pondrá en cola las actualizaciones entrantes hasta que haya un lugar para colocarlas). El nombre de la suscripción es "counts-by-room" , y toma un argumento:la ID de la sala actual. He envuelto esto dentro de Deps.autorun para que como Session.get('roomId') cambios, el cliente se dará de baja automáticamente del conteo de la sala anterior y se volverá a suscribir al conteo de la nueva sala.

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

Finalmente, tenemos el documento en Counts y podemos usarlo como cualquier otra colección de Mongo en el cliente. Cualquier plantilla que haga referencia a estos datos se volverá a dibujar automáticamente cada vez que el servidor envíe un nuevo recuento.

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