Publicar documentos en una colección a un cliente de meteors dependiendo de la existencia de un documento específico en otra colección (publicar-con-relaciones)

Tengo dos colecciones

  1. Ofertas (campos relevantes: _ id )
  2. ShareRelations (campos relevantes: receiverId y offerId )

y me gustaría publicar solo Ofertas para el usuario conectado que se le han compartido.

En realidad, estoy haciendo esto mediante el uso de una matriz de ayuda (visibleOffers) que llené mediante un bucle para cada ShareRelations y utilizo esta matriz más adelante en el buscador Offers.find como $ in.

Me pregunto si esta podría ser la forma de meteoro para hacer esto, o si podría hacerlo con menos y / o un código más bonito.

Mi código real para publicar las Ofertas es el siguiente:

Meteor.publish('offersShared', function () { // check if the user is logged in if (this.userId) { // initialize helper array var visibleOffers = []; // initialize all shareRelations which the actual user is the receiver var shareRelations = ShareRelations.find({receiverId: this.userId}); // check if such relations exist if (shareRelations.count()) { // loop trough all shareRelations and push the offerId to the array if the value isn't in the array actually shareRelations.forEach(function (shareRelation) { if (visibleOffers.indexOf(shareRelation.offerId) === -1) { visibleOffers.push(shareRelation.offerId); } }); } // return offers which contain the _id in the array visibleOffers return Offers.find({_id: { $in: visibleOffers } }); } else { // return no offers if the user is not logged in return Offers.find(null); } }); 

Además, la solución real tiene la desventaja de que si se crean nuevas relaciones de recurso compartido, la colección de Ofertas en el cliente no se actualiza al instante con la oferta recientemente visible (léase: se requiere recargar la página. Pero no estoy seguro si esto es el caso debido a este método de publicación o debido a algún otro código y esta pregunta no es primaria debido a este problema).

    Lo que estás buscando es una unión reactiva. Puede lograr esto usando directamente un observe en la función de publicación, o usando una biblioteca para hacerlo por usted. Meteor core se espera que tenga una biblioteca de join en algún momento, pero hasta entonces recomendaría usar publish-with-relations . Eche un vistazo a los documentos, pero creo que la función de publicación que desea se ve así:

     Meteor.publish('offersShared', function() { return Meteor.publishWithRelations({ handle: this, collection: ShareRelations, filter: {receiverId: this.userId}, mappings: [{collection: Offers, key: 'offerId'}] }); }); 

    Esto debe publicar de manera reactiva todas las ShareRelations para el usuario y todas las Offers asociadas. Esperemos que publicar ambos no sea un problema.

    PWR es un paquete bastante legítimo: muchos de nosotros lo usamos en producción y Tom Coleman contribuye a ello. Lo único que le advierto es que a partir de este escrito, la versión actual en la atmósfera (v0.1.5) tiene un error que dará lugar a una pérdida de memoria bastante grave. Hasta que se vea afectado, consulte la publicación de mi blog sobre cómo ejecutar una copia local actualizada.

    actualización 2/5/14:

    El blog Descubrir meteoro tiene una excelente publicación sobre uniones reactivas que recomiendo leer.

    La forma de hacerlo es en la línea de esta pregunta usando observeChanges (). Aún tratando de encontrar la manera de hacer que todo funcione para mi ejemplo, vea Meteor, One to Many Relationship & add field only to client side collection in Publish?

    Puede usar el paquete de publicación reactiva (soy uno de los autores):

     Meteor.publish('offersShared', function () { // check if the user is logged in if (this.userId) { this.autorun(function (computation) { // initialize helper array var visibleOffers = []; // initialize all shareRelations which the actual user is the receiver var shareRelations = ShareRelations.find({receiverId: this.userId}, {fields: {offerId: 1}}); // loop trough all shareRelations and push the offerId to the array if the value isn't in the array actually shareRelations.forEach(function (shareRelation) { if (visibleOffers.indexOf(shareRelation.offerId) === -1) { visibleOffers.push(shareRelation.offerId); } }); // return offers which contain the _id in the array visibleOffers return Offers.find({_id: { $in: visibleOffers } }); }); } else { // return no offers if the user is not logged in return Offers.find(null); } }); 

    Simplemente puede ajustar su código no reactivo existente en una autorun y comenzará a funcionar. Solo tenga cuidado de ser preciso en qué campos consulta, porque si consulta en todos los campos, la autorun se ejecutará ShareRelations en cualquier cambio de campo de ShareRelations , no solo de offerId .