Confusion over MongoDB collection in server and client contexts


#1

Hi!

I’m not sure if that title is the right way to ask my question but I was just reading an article on how to accomplish (reactive) joins with MongoDB and was prompted to start this topic. His code is a great example of my confusion.

SERVER

Meteor.publish('topPosts', function() {
  return Posts.find({}, {sort: {score: -1}, limit: 50});
});

Meteor.publish('authors': function(userIds) {
  return Meteor.users.find({_id: {$in: userIds}});
});

CLIENT

Router.map(function() {
  this.route('topPosts', {
    waitOn: function() {
      // tell the router to wait until topPosts's data is available to load the route
      return Meteor.subscribe('topPosts');
    },
    data: function() {
      // return all posts currently available on the client as the route's data context
      return Posts.find(); // <-- THIS RIGHT HERE
    },
    before: function() {
      // let's make sure that the topPosts subscription is ready and the posts are loaded
      if (this.data()) {
        // we can then extract the userIds of the authors
        var userIds = this.data().map(function(p) { return p.userId });
        // and add the authors subscription to the route's waiting list as well
        this.subscribe('authors', userIds).wait();
      }
    }
  });
});

The line I’m confused about is return Posts.find(); on the client. What is Posts in this context and what is it comprised of? It’s not the same as Posts on the server, right? Because if it was then wouldn’t that make Meteor.publish pointless? And it’s not topPosts because he had just previously subscribed to that.

I think my confusion can be summed up in one sentence: How can the MongoDB collection be available at both the server and client?


#2

Read “Meteor: Common Mistakes” by David Weldon, as it directly explains this issue and touches on some other assumptions your code is making that could turn out to be bad things.

Note that you’re publishing the entire user document in your authors publication, including sensitive information. You should always specify which fields to include in any publication that touches the users collection.

Posts.find() will be the 50 sorted posts you published, unless you’re also currently publishing other posts (in which case they will be merged across publications). Posts.find() on the client says “give me a cursor pointing to all of the documents in the Posts collection that I have”. What’s available on the client is dictated by your publications (unless you have the autopublish package enabled, in which case you’ll have the entire database on the client).


#3

Hi @rahul

This is not my code. It was taken from an article by Tom Coleman. …and now that I’m looking at my post it appears the reference is not being included like it should be. The article can be found at https://www.discovermeteor.com/blog/reactive-joins-in-meteor/.

I’ve read the Common Mistakes article (and I looked it over again) but I don’t know which section you’re referring to that “directly explains this issue.” If you’re talking about “Published Secrets” that’s not actually what my question here is about.

I think you’ve covered my question in your last paragraph. If I understand it, Posts on the client is comprised of each of the publications from the server for that collection?


#4

Oh, sorry about that, I must have missed you saying that in your first paragraph :slight_smile: Embarrassing :grimacing:

Anyway, yes, Posts on the client combines the different publications using something called the Merge Box. @arunoda wrote about it here: https://meteorhacks.com/understanding-mergebox.html