withTracker - No Subscription refresh when publication criteria depends on another Collection


#1

Hi everyone, The app beeing a bit complex I will try to explain my problem with a simple example.

Let’s say I have two collections, users and books.

And I want a publication to show only the books where book owners are users that are “approved”. I have a code similar to this :

Meteor.publish('approved.users.books', function() {
   let approvedUsers = Meteor.users.find({ approved : true}).fetch()
   let approvedUsersId = []
   for (let j = 0; j < approvedUsers.length; j++){
      approvedUsersId.push(approvedUsers[j]._id)
   }

  Return Books.find({ owner : { $in : approvedUsersId}})

However it seems to me (I say seems cause i ain’t 100% sure problem is coming from here but almost) that if I have a button my website that would change the status of a User and set it to “approved” then this 'approved.users.books" publication/subscription will not rerender with the books from this last users. (I am talking the subscribtion been into a withTracker HOC.

Is there a way to force a refresh of the book publication when there is a change on the users status ?

Thank you a lot in advance for your help !


#2

The problem you have run into is described here:

In short, unlike with client side code, changes to the ‘Meteor.users.find()’ here will not cause the publication to be rerun. So joins inside publications, i.e. with reactive data, are not that simple. There are some solutions though.

Firstly, do you really need reactivity? If not, you could push the data to the client with a method, perform any joins inside it and be done with it. Works well, but not reactive.

Second, you could subscribe to both collections separately and perform the joins client side. Subscription to the Books collection would then be made only after data from Meteor.users has arrived. Nice and simple, but means several round trips between the client and server so UX may suffer.

Third, in some cases you can just overpublish the data, i.e. dump all relevant data to the client and then filter as necessary client side. This retains reactivity and is simple, but of course only makes sense if the data sets are really small.

Finally, package magic. cultofcoders:grapher or reywood:publish-composite. Have not used these so cannot comment further.


#3

Thanks for the leads. Here are some comment :

Yes I do need reactive (so far my only way to solve it was to force a refresh when the user gets “approved” but I felt like going back 10 years in term of UX). As In my case the “approved” status gives you access to a private chat in the sidebar that is then lively updated.

Unfortunately I can not overpublish as the data I want to access after beeing approved should not be accessible while not approved so in term of security it does not work.

I read about Reactive joints between collection/publicatoins but still very blur to me. Couldn’t find a clear answer yet.

Maybe the double subscription could work but I am not sure how to deal with it in real. Will check the packages you propose.

Thanks again, hope to get more leads from others too if possible.


#4

If you need reactive joins, then @vooteles package suggestions are worth investigating. You could also look at tunguska:reactive-aggregate, which uses MongoDB’s aggregation pipeline, and so supports MongoDB’s $lookup operator (equivalent to SQL’s LEFT OUTER JOIN).