gushags gushags - 2 months ago 39
Javascript Question

Meteor publish-composite and nested collection

I am trying to build an app that has a many to many relationship in Meteor. There will be jobs, clients and users collections. Clients can have multiple jobs, and most importantly multiple users can work on the same job.

I have the jobs collection set up as follows in my fixtures file:

Jobs.insert({
jobNum: 'Somejob',
clientId: 'XXXXXXXX',
clientName: 'Some Client',
rate: XX,
userNames: [
{userId: user1._id},
{userId: user2._id}
],
active: true
});


I am publishing according to the readme for publish-composite, but I cannot get the users to publish to the client. Here is the publication code:

Meteor.publishComposite('jobsActive', {
find: function() {
// Find all active jobs any client
return Jobs.find({active: true});
},

children: [
{
find: function (job) {
// Return a client associated with the job
return Clients.find({_id: job.clientId});
}
},
{
find: function (job) {
// Return all users associated with the job
// This is where the problem is
return Meteor.users.find({_id: job.userNames.userId});
}
}
]
});


I can't figure out how to correctly find over an array. I tried a number of things and nothing worked. Is this possible? Or do I need to go about this in another way? I've thought about referencing jobs in the users collection, but there will be far more jobs than users, so it seems to make more sense like this.

BTW, I did subscribe to 'jobsActive' as well. The other two collections are coming over to the client side fine; I just can't get the users collection to publish.

Thanks for any help and ideas.

Answer

job.userNames.userId doesn't exist in your collection. job.userNames is an array of objects which have the key userId.

Try something like _.map( job.userNames, function( users ){ return users.userId } ).

Your code will be:

Meteor.publishComposite('jobsActive', {
    find: function() {
        return Jobs.find({active: true});
    },
    children: [
        {
            find: function (job) {
                return Clients.find({_id: job.clientId}); 
            }
        },
        {
            find: function (job) {
                return Meteor.users.find({ _id: { $in: _.map( job.userNames, function( users ) { return users.userId } ) } });
            }
        }
    ]
});