Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribing to Meteor.Users Collection

Tags:

mongodb

meteor

// in server.js
Meteor.publish("directory", function () {
return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});
});

// in client.js
Meteor.subscribe("directory");

I want to now get the directory listings queried from the client like directory.findOne() from the browser's console. //Testing purposes

Doing directory=Meteor.subscribe('directory')/directory=Meteor.Collection('directory') and performing directory.findOne() doesn't work but when I do directory=new Meteor.Collection('directory') it works and returns undefined and I bet it CREATES a mongo collection on the server which I don't like because USER collection already exists and it points to a new Collection rather than the USER collection.

NOTE: I don't wanna mess with how Meteor.users collection handles its function... I just want to retrieve some specific data from it using a different handle that will only return the specified fields and not to override its default function...

Ex:

Meteor.users.findOne() // will return the currentLoggedIn users data
directory.findOne() // will return different fields taken from Meteor.users collection. 
like image 894
o2kevin Avatar asked Aug 08 '14 08:08

o2kevin


People also ask

What does Meteor subscribe do?

The Meteor. publish function is used on the server to define what data should be available to users of the application. The Meteor. subscribe function is used on the client to retrieve the data that's published from the server.

How does meteor publishing work?

To publish records to clients, call Meteor. publish on the server with two parameters: the name of the record set, and a publish function that Meteor will call each time a client subscribes to the name. Publish functions can return a Collection.


2 Answers

If you want this setup to work, you need to do the following:

Meteor.publish('thisNameDoesNotMatter', function () {
  var self = this;
  var handle = Meteor.users.find({}, {
    fields: {emails: 1, profile: 1}
  }).observeChanges({
    added: function (id, fields) {
      self.added('thisNameMatters', id, fields);
    },
    changed: function (id, fields) {
      self.changed('thisNameMatters', id, fields);
    },
    removed: function (id) {
      self.removed('thisNameMatters', id);
    }
  });

  self.ready();

  self.onStop(function () {
    handle.stop();
  });

});

No on the client side you need to define a client-side-only collection:

directories = new Meteor.Collection('thisNameMatters');

and subscribe to the corresponding data set:

Meteor.subscribe('thisNameDoesNotMatter');

This should work now. Let me know if you think this explanation is not clear enough.

EDIT

Here, the self.added/changed/removed methods act more or less as an event dispatcher. Briefly speaking they give instructions to every client who called

Meteor.subscribe('thisNameDoesNotMatter');

about the updates that should be applied on the client's collection named thisNameMatters assuming that this collection exists. The name - passed as the first parameter - can be chosen almost arbitrarily, but if there's no corresponding collection on the client side all the updates will be ignored. Note that this collection can be client-side-only, so it does not necessarily have to correspond to a "real" collection in your database.

Returning a cursor from your publish method it's only a shortcut for the above code, with the only difference that the name of an actual collection is used instead of our theNameMatters. This mechanism actually allows you to create as many "mirrors" of your datasets as you wish. In some situations this might be quite useful. The only problem is that these "collections" will be read-only (which totally make sense BTW) because if they're not defined on the server the corresponding `insert/update/remove' methods do not exist.

like image 70
Tomasz Lenarcik Avatar answered Sep 21 '22 23:09

Tomasz Lenarcik


The collection is called Meteor.users and there is no need to declare a new one on neither the server nor the client.

Your publish/subscribe code is correct:

// in server.js
Meteor.publish("directory", function () {
return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});
});

// in client.js
Meteor.subscribe("directory");

To access documents in the users collection that have been published by the server you need to do something like this:

var usersArray = Meteor.users.find().fetch();

or

var oneUser = Meteor.users.findOne();
like image 21
Tobias Avatar answered Sep 23 '22 23:09

Tobias