Last active
May 19, 2016 15:27
-
-
Save chrisbolin/e78d7eefb2ee052cff0f5b0d00fcc024 to your computer and use it in GitHub Desktop.
Meteor Populate / Join (Quick & Dirty)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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