I just spent the last few hours developing a new feature for Basecamp Insights. The idea is to create a client-side activity feed that monitors activity in four different collections in real time. I decided that the best way to go about this would be to reactively join the relevant documents from each of those four collections on the server and then publish them to a client side pseudo-collection. Alternatively, we could send all four collections down to the client and then assemble the activity feed from there. In that case however, we would be over-publishing documents if its just the activity feed that the client is interested in. So with a reactive join approach, although we are asking the server to do a little more work, we are minimizing wait times for the client by only publishing exactly what is needed.
To reiterate, the server is joining four different collections into a single pseudo-collection that is published to the client. In the code below, you will see the same patterns repeated four times. For each of those four collections, we are essentially doing two things.
First, when the publish function first runs, for each of the four collections we:
Call the find method, using a few selectors to find only a subset of documents
Call the forEach method to iterate through each returned document
Call self.added on each iteration in order to add that document to our pseudo-collection.
After we have added the initial documents to our pseudo-collection, we can now call the observeChanges method on each of those four collections so that we can update the pseudo-collection with any relevant changes. When we see a change we update the pseudo-collection by calling self.added and self.removed. Although this section appears at the top of the code below, we use the initializing variable to skip over it when the publish function first runs. We don’t want to add the same documents to our pseudo-collection twice.
Finally, when we see the self.onStop() event, we call .stop() on each of our observeChanges handler functions so that we stop observing changes.
On the client, we create and subscribe to the new collection with:
Below is the code for the publish function. The same basic pattern should work for reactively joining an arbitrary number of collections and publishing the result to the client. If anyone can suggest a simpler approach for multiple reactive joins in Meteor, please reach out to me on Twitter!