Skip to content

Instantly share code, notes, and snippets.

@chrisbolin
Last active May 19, 2016 15:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisbolin/e78d7eefb2ee052cff0f5b0d00fcc024 to your computer and use it in GitHub Desktop.
Save chrisbolin/e78d7eefb2ee052cff0f5b0d00fcc024 to your computer and use it in GitHub Desktop.
Meteor Populate / Join (Quick & Dirty)
// quick and dirty populating ("joining") in Meteor
Mongo.Collection.prototype.findAndPopulate = function (selector, options, populates) {
/*
selector and options: from Mongo.Collection.prototype.find(selector, options)
populates: [Object] or Object
[{id, as, from}] or {id, as, from}
e.g. {id: 'userId', as: 'thisUser', from: Users}
will look up doc.userId in Users and assign to doc.thisUser
--> doc.thisUser = Users.findOne(doc.userId);
*/
check(populates, Match.OneOf(Object, Array));
if (!_.isArray(populates)) {
populates = [populates]; // always operate on an Array of Objects
}
const documents = this.find(selector, options).fetch();
// build cache. only run one query for each collection populated from
populates = populates.map(populate => {
const ids = _.pluck(documents, populate.id);
const query = {_id: {$in: ids}};
populate.cache = _.indexBy(
populate.from.find(query).fetch(),
'_id' // index by id so it's fast to find for each document
);
return populate;
});
// populate each document individually
return documents.map(doc => {
// run each populate
populates.forEach(populate => {
// fetch from cache
doc[populate.as] = populate.cache[doc[populate.id]];
});
return doc;
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment