Pub/sub not working as expected


#1

This is potentially a dumb question and I’m overlooking something simple.

So normally, if you publish something like this:

Meteor.publish('things', function () {
  return Things.find({ hidden: false });
});

This will publish all the things that are not hidden. And if new things get added to the database, they’ll automatically show up on the client side as long as a .find() is being called within a reactive context.

I’ve got something a bit different going on. I want to basically publish only the attachments for the “item” that the user is currently viewing:

Meteor.publish('attachments', function (itemType, itemId) {
  console.log('publishing attachments');
  const model = getModelFromType(itemType);

  if (model) {
    const item = model.findOne(itemId);

    if (item) {
      return Attachments.find({ _id: { $in: item.attachments } });
    }
  }

  this.ready();
});

getModelFromType is my own function which takes a string such as 'REPORT' and returns the corresponding Astronomy class. So I’m just finding the Report based on the ID passed in, and fetching it, and then publishing the attachments based on the attachment IDs that are linked to that Report.

Upon initial loading of the page, it works great. But if I add a new attachment belonging to this report, it doesn’t show up unless I do a hard reload of the page. With the first publication code above:

Meteor.publish('things', function () {
  return Things.find({ hidden: false });
});

Why does this work like magic and return newly-added items, but my implementation with attachments above does not?


#2

I can see what the issue is. Since the publication is finding specific IDs, that data set never changes and so it doesn’t trigger the sending of new data to the client. I suppose I should try fetching the item’s attachments on the client side, and pass a list of those IDs to the .subscribe() call.


#3

This is the standard reactive join problem.

There is a lot of info about this, including:
https://www.discovermeteor.com/blog/reactive-joins-in-meteor

and Arunoda’s
https://bulletproofmeteor.com/database-modeling/reactive-joins

There are different approaches to this, including de-normalization, using extensions, manually coding and giving up on certain aspects of reactivity in exchange for simplicity and performance.


#4

Yep… time to change my logic around a bit! I’ll be using the publish-composite package.

Thanks!


#5

Take into account that it incurs overhead.

If the relationship between items and attachments is one-to-many (one item, many attachments), you can consider storing the itemId in the attachment documents (and using an index), which will allow you to get the same data using a single query.

I answered what seems to be a similar question on StackOverflow recently. Hope it helps!


#6

I like that idea. I didn’t do it initially because I felt it was redundant to have an item with an attachments property that contained an array of attachment IDs. But adding an itemId property in the attachment schema is a very small price to pay in order to have a more efficient publication, for sure.