Reputation: 5629
Using Meteor:
I have a list of messages in Messages which store a userId.
Messages = new Mongo.Collection('messages');
// example of message data:
{
authorId: 'XFdsafddfs1sfd', // corresponding to a Meteor.userId
content: 'some Message'
}
And I'm publishing both the messages and the existing users.
Meteor.publish('messages', function () {
return Messages.find({});
});
Meteor.publish('users', function () {
return Meteor.users.find({});
});
Currently I can grab the list of messages and add the usernames based on the userIds. Since users can change their usernames & profile information, it doesn't make sense to add user data to the collection, just the userIds.
var messages = Messages.find({}).fetch();
var messages.forEach(function(message) {
message.username = Meteor.users.find(message.authorId).fetch() [0].username; // ugly
});
This code works, but involves a lot of wasteful calls. I want to know how to accomplish this in a better way.
In Meteor, what is the most efficient & cleanest way to pair user data with a collection containing userIds?
Upvotes: 4
Views: 2493
Reputation: 67
This is a common use case: storing ids of other collections in the db and using human readable arguments on the UI.
In Meteor the collection.find() function offers to pass a transformation callback for this use case.
var cursor = messages.find(
{},
{
transform: transformMessage
}
);
The transform function can now directly modify your object, to add/modify/delete the properties of your fetched object (attention: don't modify/delete on client side for security reasons: instead use filters on the server side and allow/deny).
function transformMessage(message) {
var user = Meteor.users.findOne(message.authorId);
if (user) {
var username = user.username;
message.username = username;
}
return message;
};
The great benefit of this way: You are still working with the cursor and preventing fetch(). And of course, cleaner code.
Upvotes: 6