How to publish a collection that depends on another?

I’ve got two collections, Conversations and Messages. I want the client only to subscribe to conversations they’re a member of, and the “messages” publication should only return messages that belong to a conversation that the user is a member of.

I’m having a heck of a time getting this working though. How do I make the messages publication depend on what conversations returns? This doesn’t work:

Meteor.publish('messages', function (orgId) {
  if (!this.userId) {
    this.ready();
    return null;
  }

  const conversationIds = Conversations.find({
    $or: [
      { owner: { $eq: this.userId } },
      { members: { $eq: this.userId } },
    ],
  }).fetch().map(conv => conv._id);

  const selector = {
    conversationId: { $in: conversationIds },
    orgId,
  };

  return Messages.find(selector);
});

…since the publication does not re-run when Conversation changes. And you can’t use Tracker on the server.

1 Like

I have a feeling reywood:publish-composite is the answer…

Yeah I have had this same issue.

In my scenario I always knew when I needed to re-subscribe, in which case that is what I did, I just ran the same subscription call again and it updated the publication.

I think it would be a little more difficult if you needed to make it reactive based on outside influences (other users adding you to a conversation). I am sure someone else has dealt with this before.


Keen to see what people suggest on this one.

Yep, that worked, as far as I can tell so far!

Meteor.publishComposite('messages', function (orgId) {
  return {
    find() {
      // if (!this.userId) {
      //   this.ready();
      //   return null;
      // }

      return Conversations.find({
        $or: [
          { owner: { $eq: this.userId } },
          { members: { $eq: this.userId } },
        ],
      });
    },

    children: [
      {
        find(conversation) {
          return Messages.find({
            conversationId: conversation._id,
          });
        },
      },
    ],
  }
});
1 Like

If you are still looking for reactivity on the server side, I’ve had good luck with peerlibrary:reactive-publish. As you can see from the docs, there are some gotchas to keep an eye for, but for publications that rely on what’s going on in other pubs, I’ve found this package to be a life saver!

3 Likes

Does reactive-publish work with FindFromSubscription? I may try it out later.