Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to explicitly unsubscribe from a collection?

Tags:

meteor

I have a MongoDB with a large "messages" collection; all messages belonging to a specific groupId. So have started with a publication like this:

Meteor.publish("messages", function(groupId) {
  return Messages.find({
    groupId: groupId
  });
});

and a subscription like this:

Deps.autorun(function() {
   return Meteor.subscribe("messages", Session.get("currentGroupId"));
});

This got me into trouble because initially currentGroupId is undefined but sill mongod would use up the CPU to find messages with groupId == null (although I know there are none).

Now, I tried to rewrite the publication as follows:

Meteor.publish("messages", function(groupId) {
  if (groupId) {
    return Messages.find({
      groupId: groupId
    });
  } else {
    return {}; // is this the way to return an empty publication!?
  }
});

and/or to rewrite the subscription to:

Deps.autorun(function() {
   if (Session.get("currentGroupId")) {
     return Meteor.subscribe("messages", Session.get("currentGroupId"));
   } else {
     // can I put a Meteor.unsubscribe("messages") here!?
   }
});

which both helps initially. But as soon as currentGroupId becomes undefined again (because the user navigates to a different page), mongod is still busy requerying the database for the last subscribed groupId. So how can I unsubscribe from a publication such that the mongod is stopped being queried?

like image 318
Dejan Avatar asked May 27 '13 15:05

Dejan


2 Answers

According to the documentation it must be http://docs.meteor.com/#publish_stop

this.stop() Call inside the publish function. Stops this client's subscription; the onError callback is not invoked on the client.

So something like

Meteor.publish("messages", function(groupId) {
  if (groupId) {
    return Messages.find({
      groupId: groupId
    });
  } else {
    return this.stop();
  }
});

And I guess on the client side you can just remove your if/else like in your first example

Deps.autorun(function() {
   return Meteor.subscribe("messages", Session.get("currentGroupId"));
});
like image 169
Michael Avatar answered Oct 26 '22 05:10

Michael


I found it more simple and straight-forward to call the .stop() function on the handler which is returned from the .subscribe() call:

let handler = Meteor.subscribe('items');
...
handler.stop();
like image 41
tivoni Avatar answered Oct 26 '22 07:10

tivoni