texto - mongodb avanzado
Cree una publicaciĆ³n reactiva con campos adicionales en cada documento (2)
Quiero hacer una publicación con varios campos adicionales, pero no quiero usar
Collection.aggregate
y perder las actualizaciones de mi publicación cuando cambie la colección (por lo que tampoco puedo usar
self.added
en ella).
Planeo usar
Cursor.observeChanges
para lograr eso.
Tengo dos limitaciones principales:
- No quiero publicar todos los campos de documentos.
-
Quiero usar algunos de los campos no publicados para crear nuevos.
Por ejemplo, tengo un
item
campo donde almaceno una matriz deitem
_id. No quiero publicarlo, pero quiero publicar un campoitem_count
con la longitud de mi matriz de campos
Aquí viene el enfoque:
-
Planeo encadenar las consultas de búsqueda. Nunca hice eso, así que me pregunto si es posible. La estructura de consulta general (simplificada) sería así: http://jsfiddle.net/Billybobbonnet/1cgrqouj/ (No puedo obtener el código que se muestra correctamente aquí)
-
Basado en el 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();
});
-
Agrego una bandera
initializing = true;
antes de mi consulta y lo configuré comotrue
justo antes de llamar aself.ready();
. Utilizo este indicador para cambiar mi variableitemCount
solo si seitemCount
la publicación. Entonces, básicamente, cambio miswitch
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 en grandes cambios en mi código. ¿Alguien puede confirmarme si este es el camino correcto?
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 eliminar / 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á pidiendo.
(Para ser honesto, 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 estoy malinterpretando, pero mirando el resto de tu pregunta, esta 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. Deja fuera los campos que no quieres:
MyCollection.find({}, {fields: {''a_field'':1}});
Resolver su segundo problema también es bastante fácil, sugeriría usar los paquetes de ayuda de colección . 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 agregar un objeto a un cursor y creará propiedades en los objetos devueltos que se calculan dinámicamente, no se almacenan en MongoDB.