Hi, I’m fairly new to Meteor development.
We have a use case where we display a list of posts and each post has several comments, similar to a Facebook feed. Currently we are subscribing to a “posts” publication and each post component (we are using React) is subscribing to a “comments” publication constrained to the post id.
This is similar (if not the same) to the N+1 query problem. I was wondering about the performance of this pattern in the Meteor world (i.e. websockets + mongo), is this something to be avoided? Should we change this so the parent component subscribes to both publications at once?
If you care about performance I would suggest embedding the latest comments in the post document (or even embedding them entirely if you don’t think you are going to have thousands of comments per post) and then subscribing to the comments publication only on the “post detail page” or if the user wants to see all comments (facebook doesn’t show all comments from the start either).
Still, it’s probably better to leave this optimizations for later, if you feel the publications are slowing down your app (the quote premature optimization is the root of all evil. is well knows for good reasons).
Having dealt with this quite a bit while creating the Socialize package set, I’ll chime in on this.
I personally would not use a subscription that depends on another subscription. The reason for this being that subscriptions block on a per connection basis. Each new subscribe call initiated by a specific client will not complete until any previous subscriptions initiated by that client have completed.
You could go the route @Matteo_Saporiti suggests with storing comments on the post document, but really you never know how many comments you could get on one post, and pagination would be totally out with this solution as you can’t filter properly on fields below the first level due to the way meteors mergebox works. If you go the route of storing just the latest x number of comments then you end up having to keep this up to date each time a comment is added, updated or deleted which is a data integrity nightmare waiting to happen.
My recommendation is to use
reywood:publish-composite to publish the posts and a subset of related comments for each post. Limit the posts in the subscription to somewhere between 10-20. You can always grab the next batch when needed. For comments limit them to 1-3 for each post. You can have a more comments link to subscribe to the rest of the comments for a specific post, or even a modal that opens to a full view of the post and all its comments when the user click on the post. This approach will give you the best trade-offs for all of the issues you might run into.
Well, data duplication in MongoDB is quite common, you have to weight the pros vs the cons.
The $slice operator make it quite easy to manage a fixed list of comments so it’s not that bad.
And since you probably want to keep the number of total comments in the post document you would still need to update the post document every time a new comment is added/deleted anyway.
It all depends on the performance requirements and how the application work, I don’t think there is a single “correct” solution what works for every use case.
He can, for example, just do a simple custom publication and fetch manually the latest comments in the added/update callbacks of observeChanges, and if he needs fancier stuff move to something based on publish-composite, or embed the comments if he finds that the multiple reads slow down the app.