Publish documents in a collection to a meteor client depending on the existence of a specific document in another collection (publish-with-relations)

后端 未结 3 1741
[愿得一人]
[愿得一人] 2020-11-27 07:30

I have two collections

  1. Offers (relevant fields: _id)
  2. ShareRelations (relevant fields: receiverId and offerId)
<
相关标签:
3条回答
  • 2020-11-27 08:08

    What you are looking for is a reactive join. You can accomplish this by directly using an observe in the publish function, or by using a library to do it for you. Meteor core is expected to have a join library at some point, but until then I'd recommend using publish-with-relations. Have a look at the docs, but I think the publish function you want looks something like this:

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

    This should reactively publish all of the ShareRelations for the user, and all associated Offers. Hopefully publishing both won't be a problem.

    PWR is a pretty legit package - several of us use it in production, and Tom Coleman contributes to it. The only thing I'll caution you about is that as of this writing, the current version in atmosphere (v0.1.5) has a bug which will result in a fairly serious memory leak. Until it gets bumped, see my blog post about how to run an updated local copy.

    update 2/5/14:

    The discover meteor blog has an excellent post on reactive joins which I highly recommend reading.

    0 讨论(0)
  • 2020-11-27 08:09

    You can use the reactive-publish package (I am one of authors):

    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);
      }
    });
    

    You can simply wrap your existing non-reactive code into an autorun and it will start to work. Just be careful to be precise which fields you query on because if you query on all fields then autorun will be rerun on any field change of ShareRelations, not just offerId.

    0 讨论(0)
  • 2020-11-27 08:10

    The way to do this is along the lines of this Question using observeChanges(). Still trying to figure out how to get it all working for my example, see Meteor, One to Many Relationship & add field only to client side collection in Publish?

    0 讨论(0)
提交回复
热议问题