¿Cómo “transformar” los datos devueltos a través de Meteor.publish?

Las colecciones de meteors tienen una habilidad de transformación que permite que el comportamiento se una a los objetos devueltos de mongo.

Queremos que apague autopublish para que el cliente no tenga acceso a las colecciones de la base de datos, pero aún queremos la funcionalidad de transformación.

Estamos enviando datos al cliente con un Meteor.publish / Meteor.subscribe más explícito o el mecanismo RPC (Meteor.call () / Meteor.methods ())

¿Cómo podemos hacer que el cliente de Meteor aplique automáticamente una transformación como lo hará al recuperar datos directamente con los métodos Meteor.Collection?

Si bien no puede usar transformaciones directamente, hay una forma de transformar el resultado de una consulta de base de datos antes de publicarlo. Esto es lo que el ejemplo “publicar el tamaño actual de una colección” describe aquí .

Me tomó un tiempo encontrar una aplicación realmente simple de eso, así que tal vez mi código también te ayude:

 Meteor.publish("publicationsWithHTML", function (data) { var self = this; Publications .find() .forEach(function(entry) { addSomeHTML(entry); // this function changes the content of entry self.added("publications", entry._id, entry); }); self.ready(); }); 

En el cliente, te suscribes a esto:

 Meteor.subscribe("publicationsWithHTML"); 

Pero su modelo aún necesita crear una colección (en ambos lados) que se llame ‘publicaciones’:

 Publications = new Meteor.Collection('publications'); 

Eso sí, este no es un buen ejemplo, ya que no mantiene la reactividad. Pero al principio encontré el ejemplo de recuento un poco confuso, así que tal vez lo encuentres útil.

(Meteor 0.7.0.1): el meteor permite que el comportamiento se una a los objetos devueltos a través del pub / sub.

Esto es de una solicitud de extracción que envié al proyecto de meteors.

 Todos = new Meteor.Collection('todos', { // transform allows behavior to be attached to the objects returned via the pub/sub communication. transform : function(todo) { todo.update = function(change) { Meteor.call('Todos_update', this._id, change); }, todo.remove = function() { Meteor.call('Todos_remove', this._id); } return todo; } }); todosHandle = Meteor.subscribe('todos'); 

Todos los objetos devueltos a través del tema ‘todos’ tendrán la función update () y remove (), que es exactamente lo que quiero: ahora adjunto un comportamiento a los datos devueltos.

Tratar:

 let transformTodo = (fields) => { fields._pubType = 'todos'; return fields; }; Meteor.publish('todos', function() { let subHandle = Todos .find() .observeChanges({ added: (id, fields) => { fields = transformTodo(fields); this.added('todos', id, fields); }, changed: (id, fields) => { fields = transformTodo(fields); this.changed('todos', id, fields); }, removed: (id) => { this.removed('todos', id); } }); this.ready(); this.onStop(() => { subHandle.stop(); }); }); 

Actualmente, no puede aplicar transformaciones en el servidor a colecciones publicadas. Vea esta pregunta para más detalles. Eso te deja transformando los datos en el cliente o usando un método de meteoros. En un método, puede hacer que el servidor haga lo que quiera con los datos.

En uno de mis proyectos, realizamos nuestra consulta más cara (une varias colecciones, desnormaliza los documentos y recorta los campos innecesarios) a través de una llamada a un método. No es reactivo, pero simplifica enormemente nuestro código porque toda la transformación ocurre en el servidor.

Para extender la respuesta de @Christian Fritz, con Reactive Solution usando peerlibrary: reactive-publish

 Meteor.publish("todos", function() { const self = this; return this.autorun(function(computation) { // Loop over each document in collection todo.find().forEach(function(entry) { // Add function to transform / modify each document here self.added("todos", entry._id, entry); }); }); });