I would like to share this doubt, and how would you do it.
Imagine that I have 2 collections, ‘Books’ and ‘Authors’. Every document in the book collection has an author field with an ‘_id’ reference to the specific author in the ‘Authors’ Collection.
Now I want to show in the client a list of my books. I can do a simple subscription to 10 books, and show them in a list. The problem comes when I want to show the name of the author. I would do it like this:
list.html
{{ #each book in books }}
{{ book.title }}
...
{{ authorName book.authorId }}
{{ /each }}
list.js
...helpers({
books: function () {
return Books.find();
},
authorName: function (id) {
return Authors.findOne({ _id: id }).name;
}
})
The problem is that I have to subscribe to all the ‘Authors’ collection. With a small collection is not a problem. But imagine that I have 5000 authors.
Best solution here is to publish using a package like Publish Composite. Also, if you have 10,000 books, only publish a small subset for each subscription to maintain performance.
If you didn’t want to head down the publish composite route:
Meteor.publish('books', function () {
let books = Books.find({}, { limit: 10 });
// Grab the relevant ids
let authorIds = _.pluck(books.fetch(), 'authorId');
// Scope your query and result
let authors = Authors.find({ _id: { $in: authorIds } }, { fields: { _id: 1, name: 1 } });
// Return only the docs you need
return [books, authors];
});
I do not like publish composite because it is creating a subscription for each author, and it is going to make your system so slow!
what I ended up doing and haven’t seen anywhere is just publish it the way @vigorwebsolutions suggested but use subscribe manager package. on the client in the helper (for Blaze) or another place check the data, if you don’t have an author of a book in your minimongo just restart the subscribe and you will get a new set of data. it works great for me.
Yeah, I should’ve mentioned that there are caveats to that solution. I agree that publish composite can be overkill/taxing on the server when it’s not always needed.
Also, I’ve been looking more at non-reactive solutions when they make sense, and book-author seemed to fit that paradigm for me.
It wouldn’t create a subscription for each author… Maybe you mean it would make a query per book to get the record of the author, you are right. The really awesome thing about Mongodb is that query’s on indexes (especially _id’s) are super fast, so as long as you limit your books query reasonably (say 30 books at a time), your performance shouldn’t suffer.
First, I’d start with optimizing the database schema, before I do any publication magic that will slow down the servers.
Just provide the name of the author in your book collection together with his id. Mongo is a NoSQL database and fully supports this way of structuring. And it’s not like you’re going to change the author’s name for a book every week.