0

I'm trying to publish "friends" from the users Collection. There is a field on every account that saves all friend-ids (called addressbook). But publishing doesn't work I'm only getting my own account (as non admin) e.g. if i call Meteor.users.find().fetch() on the console. If I do it the way above the console logs the following:

I20140107-17:22:38.492(1)? ---------------------------------------[object Object]
I20140107-17:22:38.497(1)? [ { _id: 'X6XXyD64AW4CvXG6m',
I20140107-17:22:38.498(1)? createdAt: Tue Jan 07 2014 17:10:43 > GMT+0100 (CET)
I20140107-17:22:38.498(1)? emails: [ [Object] ],
I20140107-17:22:38.498(1)? services: { password: [Object], resume: [Object] },
I20140107-17:22:38.499(1)? username: 'test' } ]

so no addressbook is presented

Here a snippet of my code:

Server:

Meteor.publish("users", function(){
    if (Roles.userIsInRole(this.userId, ["admin"]))
        return Meteor.users.find();
    else
        return Meteor.users.find({_id : this.userId}, {fields: {username: 1, id_:1, emails:1, addressbook:1, createdAt:1}});
});

Meteor.publish("friends", function(){
    var addressbook = Meteor.users.find({_id: this.userId}, {limit:1} , {fields: {addressbook:1}});
    console.log("---------------------------------------" + addressbook);
    console.log(addressbook.fetch());

    //return Meteor.users.find({_id :{ $in : addressbook}}, {fields : {username:1, emails: 1}});

Client:

Deps.autorun(function() {
    Meteor.subscribe("friends");
    Meteor.subscribe("users");
});

How do i publish the users which are stored by their ids to the field addressbook (or at least their emails and usernames)? Is there a better way to combine the publish ?

Thanks in advance!

kerosene
  • 930
  • 14
  • 31

1 Answers1

0

There are a few things wrong with your friends publish function:

  1. You don't really need limit when fetching a single document - just use findOne.
  2. options for a find is a single object. So you'd want: {limit: 1, fields: {addressbook: 1}}
  3. A document must be fetched (or you have to use findOne) before it's values can be accessed.
  4. fetch is a function that is available on a cursor (the result of a find). addressbook is just an array.

It seems like you were otherwise on the right track. Give this a try:

Meteor.publish('friends', function() {
  var addressbook = Meteor.users.findOne(this.userId).addressbook || [];
  return Meteor.users.find({_id: {$in: addressbook}}, {fields: {username: 1, emails: 1}});
});

However, it's worth mentioning that friends won't be reactive if the addressbook changes. For that you need a reactive join. Please see this question.

Community
  • 1
  • 1
David Weldon
  • 63,632
  • 11
  • 148
  • 146
  • Thanks for your suggestions. I already tried it this way, but it throws an exception on serverside (copied your code), see full log here: http://pastebin.com/0EB4bMZF I used a console.log(addressbook); and it shows that addressbook is always undefined :/ – kerosene Jan 07 '14 at 19:04
  • You'd get an error if `addressbook` was not defined. I modified to code to deal with that case. If the fetch isn't returning a document with an `addressbook`, then either the user isn't logged in or the user document doesn't have an `addressbook`. Check that `this.userId` is valid and open a database connection on the console with `meteor mongo`. When the db connection is open, run `db.users.findOne(userId)` where `userId` is the one you got from above. See if the document has an `addressbook`. If it doesn't then it isn't being set, which is outside the scope of this question. – David Weldon Jan 07 '14 at 19:19
  • Thank you! Now everything run smoothly! There was a old id-entry (that didn't exist any longer) in the addressbook so that was the reason for an exception. – kerosene Jan 07 '14 at 19:56