Cree una publicación reactiva con campos adicionales en cada documento

Quiero hacer una publicación con varios campos adicionales, pero no quiero usar Collection.aggregate y perder mis actualizaciones de publicación cuando cambie la colección (así que tampoco puedo usar self.added en ella).

Planeo usar Cursor.observeChanges para lograr eso. Tengo dos limitaciones principales:

  1. No quiero publicar todos los campos de documentos
  2. Quiero usar algunos de los campos no publicados para crear nuevos. Por ejemplo, tengo un item campo donde almaceno una matriz de item _id. No quiero publicarlo, pero quiero publicar un campo item_count con la longitud de mi matriz de campo

Aquí viene el enfoque:

  1. Planeo encontrar citas en cadena. Nunca lo hice, así que me pregunto si es posible. La estructura de consulta general (simplificada) sería la siguiente: http://jsfiddle.net/Billybobbonnet/1cgrqouj/ (no puedo ver el código aquí)

  2. En función del ejemplo de conteo en la documentación de Meteor , almaceno mi consulta en un handle variable para detener la notificación de cambios si un cliente cancela la suscripción:

 self.onStop(function () { handle.stop(); }); 
  1. Agrego un indicador initializing = true; antes de mi consulta y lo configuré en true justo antes de llamar a self.ready(); . Uso esta bandera para cambiar mi variable itemCount solo si la publicación está inicializada. Entonces, básicamente, cambio mi switch así:
 switch (field) { case "item" if (!initializing) itemCount = raw_document.item.length; break; default: } 

Quería comprobar que este enfoque es bueno y posible antes de comprometerme con grandes cambios en mi código. ¿Alguien puede confirmarme si este es el camino correcto a seguir?

Es relativamente fácil mantener los campos privados incluso si son parte de la consulta de la base de datos. El último argumento para self.added es el objeto que se pasa al cliente, por lo que puede quitar / modificar / eliminar los campos que está enviando al cliente.

Aquí hay una versión modificada de tu violín. Esto debería hacer lo que estás pidiendo. (Para ser sincero, no estoy seguro de por qué tenías algo encadenado después de la función observeChanges en tu violín, así que tal vez te esté malinterpretando, pero mirando el rest de tu pregunta debería ser. Lo siento si me equivoqué. )

 var self = this; // Modify the document we are sending to the client. function filter(doc) { var length = doc.item.length; // White list the fields you want to publish. var docToPublish = _.pick(doc, [ 'someOtherField' ]); // Add your custom fields. docToPublish.itemLength = length; return docToPublish; } var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}}) // Use observe since it gives us the the old and new document when something is changing. // If this becomes a performance issue then consider using observeChanges, // but its usually a lot simpler to use observe in cases like this. .observe({ added: function(doc) { self.added("myCollection", doc._id, filter(doc)); }, changed: function(newDocument, oldDocument) // When the item count is changing, send update to client. if (newDocument.item.length !== oldDocument.item.length) self.changed("myCollection", newDocument._id, filter(newDocument)); }, removed: function(doc) { self.removed("myCollection", doc._id); }); self.ready(); self.onStop(function () { handle.stop(); }); 

Para resolver su primer problema, debe decirle a MongoDB qué campos debe devolver en el cursor. Deje fuera los campos que no quiere:

 MyCollection.find({}, {fields: {'a_field':1}}); 

Resolver su segundo problema también es bastante fácil, le sugiero que use los paquetes de colección de ayuda . Podrías lograr esto fácilmente, así:

 // Add calculated fields to MyCollection. MyCollection.helpers({ item_count: function() { return this.items.length; } }); 

Esto se ejecutará antes de que se agregue un objeto a un cursor, y creará propiedades en los objetos devueltos que se calculan dinámicamente, no almacenados en MongoDB.

Intereting Posts