5

I understand that a a subscription is a way to flow records into a client-side collection, from this post, and others...

However, per this post, You can have multiple subscriptions that flow into the same collection.

// server
Meteor.publish('posts-current-user', function publishFunction() {
  return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10});
  // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId
}
Meteor.publish('posts-by-user', function publishFunction(who) {
  return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10});
}

// client
Meteor.subscribe('posts-current-user');
Meteor.subscribe('posts-by-user', someUser);

Now - I obtained my records via two different subscriptions, can I use the subscription to get to the records that it pulled back? Or must I requery my collection? What is the best practice for sharing that query between client and server?

I hope I'm not missing something obvious here, but executing the Meteor.subscribe function only for its side-effects seems to be losing a very useful piece of information - namely which subscription a record came from. Presumably the names of publications and subscriptions are chosen to be meaningful - it would be nice if I could get to records associated with that name.

Community
  • 1
  • 1
Dean Radcliffe
  • 2,194
  • 22
  • 29
  • possible duplicate of [how to know which docs are sent to the client in meteor](http://stackoverflow.com/questions/27737391/how-to-know-which-docs-are-sent-to-the-client-in-meteor) – David Weldon Jan 02 '15 at 22:20
  • See my comment from the question above. You probably need a transform in order to mark which documents came from which publisher. In general, it feel like a "you're doing it wrong" problem if this is actually an issue. Can you explain more about why this would be important in your use case? – David Weldon Jan 02 '15 at 22:23
  • possible duplicate of [Meteor publish/subscribe strategies for unique client-side collections](http://stackoverflow.com/questions/12223866/meteor-publish-subscribe-strategies-for-unique-client-side-collections) – malhal Aug 04 '15 at 14:48

3 Answers3

9

What you seem to want to do is maintain two separate collections of records, where each collection is populated by a different publication. If you read the DDP specification, you'll see that the server tells the client which collection (not publication) each record belongs to, and multiple publications can actually provide different fields to the same record.

However, Meteor actually lets you send records to any arbitrary collection name, and the client will see if it has that collection. For example:

if (Meteor.isServer) {
  Posts = new Mongo.Collection('posts');
}

if (Meteor.isClient) {
  MyPosts = new MongoCollection('my-posts');
  OtherPosts = new MongoCollection('other-posts');
}

if (Meteor.isServer) {
  Meteor.publish('my-posts', function() {
    if (!this.userId) throw new Meteor.Error();

    Mongo.Collection._publishCursor(Posts.find({
      userId: this.UserId
    }), this, 'my-posts');

    this.ready();
  });

  Meteor.publish('other-posts', function() {
    Mongo.Collection._publishCursor(Posts.find({
      userId: {
        $ne: this.userId
      }
    }), this, 'other-posts');

    this.ready();
  });
}

if (Meteor.isClient) {
  Meteor.subscribe('my-posts', function() {
    console.log(MyPosts.find().count());
  });

  Meteor.subscribe('other-posts', function() {
    console.log(OtherPosts.find().count());
  });
}
sbking
  • 7,630
  • 24
  • 33
3

This is what's happening:

Say that your server-side BlogPosts Mongo collection contains 500 posts from 10 different users. You then subscribe to two different subscriptions on the client:

Meteor.subscribe('posts-current-user'); // say that this has 50 documents
Meteor.subscribe('posts-by-user', someUser); // say that this has 100 documents

Meteor will see Meteor.subscribe('posts-current-user'); and proceed to download the posts of the current user to the client-side Mini-Mongo's BlogPosts collection.

Meteor will then see Meteor.subscribe('posts-by-user', someUser); and proceed to download the posts of someuser to the client-side Mini-Mongo's BlogPosts collection.

So now the client-side Mini-Mongo BlogPosts collection has 150 documents, which is a subset of the 500 total documents in the server-side BlogPosts collection.

So if you did BlogPosts.find().fetch().count in your client (Chrome Console) the result would be 150.

fuzzybabybunny
  • 5,146
  • 6
  • 32
  • 58
  • I think the question was on the client how do you only get the posts-by-user? I don't think you got that far in your answer. I believe you do a find on the client with the same query used to publish on the server. – malhal Aug 04 '15 at 14:43
0

Of course! It just depends on where you write your subscriptions. In a lot of cases you might be using Iron Router, in which case you would have a given route subscribe to just the data that you need. Then from within that route template's helper you can only query documents within that subscription.

But the general idea is that you hook up a particular subscription to a particular template.

Template.onePost.helpers({
  post: function() {
    Meteor.subscribe('just-one-post', <id of post>);
    return Posts.findOne();
  }
});

Template.allPosts.helpers({
  posts: function() {
    Meteor.subscribe('all-posts');
    return Posts.find();
  }
));
azium
  • 20,056
  • 7
  • 57
  • 79
  • The iron router case sounds interesting, and I'll try that out. I'm not sure subscribing in a helper is what I'd be comfortable with, since I'm less clear on when those subscriptions would get stopped. – Dean Radcliffe Jan 03 '15 at 07:46