Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor.publish: publish collection which depends on other collection

I have a publish function as follows:

Meteor.publish('tasks', function (name) {
    var project = Projects.findOne({name: name});

    return Tasks.find({projectId: project._id});
});

Now assume that at some point changes are made to Projects with the result that the above Projects.findOne returns a different project and so the Tasks.find will return other tasks. However the changes made to Projects doesn't republish the tasks

I've used reactivePublish, but it turns out the package has issues (and also does not have any unit tests). So, is there an easy way to make this publish function re-publish when project changes ?

like image 755
Jeanluca Scaljeri Avatar asked Oct 16 '14 07:10

Jeanluca Scaljeri


People also ask

How does meteor publishing work?

In Meteor a publication is a named API on the server that constructs a set of data to send to a client. A client initiates a subscription which connects to a publication, and receives that data.

What does Meteor subscribe do?

The Meteor. publish function is used on the server to define what data should be available to users of the application. The Meteor. subscribe function is used on the client to retrieve the data that's published from the server.


2 Answers

Overview

As of this writing, reactive joins are an unsolved problem. For a complete overview see Reactive Joins In Meteor.

Recommendations

I strongly recommend against using observeChanges directly. It's incredibly hard to get right, and easy to develop a memory leak. If you don't believe me, watch this video on EventedMind. It will make your eyes bleed.

There are several package-based solutions to this problem. The meteor guide recommends publish-composite.

If you find the idea of using a package-based solution to be unacceptable, have a close look at the Joining On The Client section from Reactive Joins In Meteor. It's clean but requires more waiting on the user's part. Also see my post on template joins if you prefer to active your subscriptions at the template level.

like image 188
David Weldon Avatar answered Sep 21 '22 21:09

David Weldon


There is a new kid on the block now. A full server-side reactive publish solution. (Disclaimer: I am one of the authors.) It is designed so that you can use it normally as you would expect with autorun. It takes care of everything automatically.

Install the package by calling meteor add peerlibrary:reactive-publish.

With the package added you can then simply do:

Meteor.publish('tasks', function (name) {
    this.autorun(function (computation) {
        var project = Projects.findOne({name: name}, {fields: {_id: 1}});

        return Tasks.find({projectId: project._id});
    });
});

Exactly as you would expect. :-)

The important part is to limit fields in the first query only to _id, otherwise autorun will be rerun every time any field of the project document changes. You do not want that.

like image 38
Mitar Avatar answered Sep 22 '22 21:09

Mitar