I have 2 collections:
- Users
- Articles
I want to subscribe articles of those users which are active:
Currently my code is:
Meteor.publish("subscribeAllArticles", function () {
// Fetching all those users who are active
var getUsers = Meteor.users.find({flag: 0}).fetch();
var userIds = [];
// Preparing array of user ids of the fetched users
if(getUsers){
for(var i = 0; i < getUsers.length; i++){
userIds.push(getUsers[i]._id);
}
}
// Getting articles of all the active users
return Articles.find({ownerId: {$in: userIds}});
});
Issue with the above code is that it is not reactive if admin deletes any users. The articles still appears even if admin deletes the specific users. When I refresh the screen then those articles disappear, but not reactively.
How do we deal with such kind of scenarios?
I think you need to map over the cursor and don’t fetch. Something like …
const userIds = Meteor.users.find({flag: 0}).map(user => user._id)
// or **************************
const getUsers = Meteor.users.find({flag: 0})
const userIds = []
getUsers.map(user => userIds.push(user._id))
There are reactive aggregate packages out there.
If you are only concerned with this use case, and then just be reactive for the user collection and then use methods to query changes as the user changes.
But reading the use case, is it really needed to be reactive?
Naah this wont help, its just another work around of for loop
Yeah actually it is needed to be reactive. This is not the real case I got there, its just to explain things in simpler way that’s all.
Don’t you think if we go for the methods way, it will break down the overall performance, don’t you agree?
I normally subscribe to the collection that is triggerring the reactivity. Then I use methods to query the changes to the other collections. This works really well for us.
I haven’t used the reactive aggregate packages. You can check them
I used aggregate packages long ago but i felt performance dip back then.
So you trigger methods from client side when ever you receive a change in a subscription right?
That is a mapping not a loop, over a cursor, not over the result of a fetch.
But do you think it would be reactive for Articles as well?
Like would it remove Articles reactively for the user who just got deleted from admin panel?
Your code is not reactive because of that fetch()
on the Users. Anyway if this is still not reactive, I guess you can still use the Publish Composite https://github.com/Meteor-Community-Packages/meteor-publish-composite.
I have used this package but I am concerned about the performance too, specially on large scales.
Because as far as I know, Mongodb is not as fast in selecting or fetching records as any structural database (mysql for example) .
Yeah that is something I was thinking of, but it would create a bit of mess while taking decisions on datasets related to articles, as I mentioned earlier in my previous comments: “This is not the real case I got there, its just to explain things in simpler way that’s all.”
So yeah for some extent I can agree with your solution.
Your issue is explained in the guide in the section ‘Publishing Relational Data’
The reason it is not reactive is :
On the server however, the reactivity is limited to the behavior of the cursors you return from your publish functions. You’ll see any changes to the data that matches their queries, but their queries will never change
The official solution is to use the publish composite package. If you don’t want to use that, you’re really limited to changing your data structure.
Seems like Publish Composite is the best solution so far.
In the meteor, you have to use publish-composite package when you have 2 or more collections in your publication.
Meteor.publishComposite
provides a flexible way to publish a set of related documents from various collections using a reactive join.
I used aggregate packages long ago but i felt performance dip back then.
Yeah same here. Aggregate is totally not recommended. I used it long time ago and I faced serious performance drop.
We do still have to talk about security though. Because while it’s nice that we have a bunch of neat features, if we were to deploy our project to the web in its current state, it’d be easy for unscrupulous people to wreak havoc official site