MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como funciona o exemplo de contagem de mensagens nos documentos do Meteor?


Obrigado por me levar a escrever uma explicação mais clara. Aqui está um exemplo mais completo com meus comentários. Houve alguns bugs e inconsistências que eu limpei. A próxima versão de documentos usará isso.

Meteor.publish é bastante flexível. Não se limita a publicar coleções existentes do MongoDB para o cliente:podemos publicar o que quisermos. Especificamente, Meteor.publish define um conjunto de documentos que um cliente pode assinar. Cada documento pertence a algum nome de coleção (uma string), possui um _id exclusivo campo e, em seguida, tem algum conjunto de atributos JSON. À medida que os documentos no conjunto mudam, o servidor enviará as alterações para cada cliente inscrito, mantendo o cliente atualizado.

Vamos definir um conjunto de documentos aqui, chamado "counts-by-room" , que contém um único documento em uma coleção chamada "counts" . O documento terá dois campos:um roomId com o ID de uma sala e count :o número total de mensagens naquela sala. Não existe uma coleção real do MongoDB chamada counts . Este é apenas o nome da coleção que nosso servidor Meteor enviará para o cliente e armazenará em um client-side coleção chamada counts .

Para fazer isso, nossa função de publicação usa um roomId parâmetro que virá do cliente, e observa uma consulta de todas as Mensagens (definidas em outro lugar) naquela sala. Podemos usar o método observeChanges mais eficiente forma de observar uma consulta aqui, pois não precisaremos do documento completo, apenas o conhecimento de que um novo foi adicionado ou removido. Sempre que uma nova mensagem é adicionada com o roomId estamos interessados, nosso retorno de chamada incrementa a contagem interna e, em seguida, publica um novo documento para o cliente com esse total atualizado. E quando uma mensagem é removida, ela diminui a contagem e envia a atualização ao cliente.

Quando chamamos observeChanges pela primeira vez , algum número de added retornos de chamada serão executados imediatamente, para cada mensagem que já existe. Em seguida, as alterações futuras serão acionadas sempre que as mensagens forem adicionadas ou removidas.

Nossa função de publicação também registra um onStop manipulador para limpar quando o cliente cancela a assinatura (manualmente ou na desconexão). Este manipulador remove os atributos do cliente e elimina o observeChanges em execução .

Uma função de publicação é executada sempre que um novo cliente se inscreve em "counts-by-room" , então cada cliente terá um observeChanges correndo em seu nome.
// 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();
  });
});

Agora, no cliente, podemos tratar isso como uma assinatura típica do Meteor. Primeiro, precisamos de um Mongo.Collection que conterá nosso documento de contagens calculadas. Como o servidor está publicando em uma coleção chamada "counts" , passamos "counts" como o argumento para o Mongo.Collection construtor.
// client: declare collection to hold count object
Counts = new Mongo.Collection("counts");

Então podemos assinar. (Você pode se inscrever antes de declarar a coleção:o Meteor irá enfileirar as atualizações recebidas até que haja um lugar para colocá-las.) O nome da assinatura é "counts-by-room" , e leva um argumento:o ID da sala atual. Eu envolvi isso dentro de Deps.autorun para que como Session.get('roomId') alterações, o cliente cancelará automaticamente a contagem do quarto antigo e reassinará a contagem do novo quarto.
// client: autosubscribe to the count for the current room
Tracker.autorun(function () {
  Meteor.subscribe("counts-by-room", Session.get("roomId"));
});

Por fim, temos o documento em Counts e podemos usá-lo como qualquer outra coleção Mongo no cliente. Qualquer modelo que faça referência a esses dados será redesenhado automaticamente sempre que o servidor enviar uma nova contagem.
// client: use the new collection
console.log("Current room has " + Counts.findOne().count + " messages.");