Mongoose plugin to enable deep population of nested models

Mongoose plugin to enable population of nested models at any level of depth. Support Mongoose 3.8.x and later. Refer to changelog for breaking changes.


Build Status Issue Stats Issue Stats


Sample usages are based on the following schemas:

var UserSchema = new Schema({})

var CommentSchema = new Schema({
  user  : {type: Number, ref: 'User'}

var PostSchema = new Schema({
  user    : {type: Number, ref: 'User'},
  comments: [{type: Number, ref: 'Comment'}],
  likes   : [{user: {type: Number, ref: 'User'}}],
  approved: {status: Boolean, user: {type: Number, ref: 'User'}}

Register plugin

// CHANGE from 1.x: need to pass in mongoose instance
var deepPopulate = require('mongoose-deep-populate')(mongoose);
PostSchema.plugin(deepPopulate, options /* more on options below */);

Perform population

On Post model:

// Use callback
Post.deepPopulate(posts, 'comments.user', function (err, _posts) {
  // _posts is the same instance as posts and provided for convenience
  posts.forEach(function (post) {
    // post.comments and post.comments.user are fully populated

// Use promise
Post.deepPopulate(posts, 'comments.user').then(...);

On an instance of Post:

// Use callback
post.deepPopulate('comments.user', function (err, _post) {
  // _post is the same instance as post and provided for convenience

// Use promise

On Query (returns the same query object to chain):

Post.find().deepPopulate('comments.user').exec(function (err, posts) { ... });
Post.findOne().deepPopulate('comments.user').exec(function (err, post) { ... });
Post.findById(id).deepPopulate('comments.user').exec(function (err, post) { ... });

Populate multiple paths

Pass paths in a space- or comma-delimited string:

post.deepPopulate('user comments.user likes.user approved.user', cb);

Or use an array of strings:

post.deepPopulate(['comments.user', 'user', 'likes.user', 'approved.user'], cb);

Specify options

Specify whitelist option to ensure only certain paths can be populated. This is to prevent potential performance and security issues if you allow API clients to supply population paths.

PostSchema.plugin(deepPopulate, {
  whitelist: [

Use the populate option to supply paths with corresponding Mongoose populate options.

PostSchema.plugin(deepPopulate, {
  populate: {
    'comments.user': {
      select: 'name',
      options: {
        limit: 5
    'approved.user': {
      select: 'name'

Use rewrite option to rewrite provided paths as well as paths in whitelist and populate. This is useful when you allow API clients to supply population paths (e.g. via query string) and want to make these paths more user-friendly. For example:

PostSchema.plugin(deepPopulate, {
  rewrite: {
    author: 'user',
    approver: 'approved.user'

// assume the query string is: ?populate=author,approver
post.deepPopulate(req.query.populate, cb);  
Overriding options

You can override the above plugin options when invoking deepPopulate.

Post.deepPopulate(posts, paths, {
  whitelist: [],
  populate: {},
  rewrite: {}
}, cb)

post.deepPopulate(paths, {
  whitelist: [],
  populate: {},
  rewrite: {}
}, cb);

Post.find({}).deepPopulate(paths, {
  whitelist: [],
  populate: {},
  rewrite: {}


The test suite will drop the database each run, so only run it against a test database. To run tests, execute this command where --db is the connection string.

gulp test --db mongodb://



  • [Feature] Return a promise when invoking deepPopulate() on model or model instance.


  • [Bug] Fix bug cannot use native ES6 Promise


  • [Bug] Fix bug populating when there is a subdocument within a linked document (see #29)


  • [Breaking] Need a mongoose instance passed to the function returned by require
  • [Feature] Support mongoose promise provider


  • [Feature] Make mongoose a peer dependency to enforce supported versions


  • [Bug] Fix bug happening when Mongoose#populate does not infer the expected schema


  • [Bug] Apply lean to populated documents


  • [Feature] Apply rewrites to whitelist and populate


  • [Feature] Add deepPopulate to Query
  • [Feature] Support space delimiter in paths


  • [Feature] Support populate options
  • [Feature] Override options per call
  • [Bug] Handle null paths and callback


  • Initial release



Related Repositories



Mongoose plugin to enable deep population of nested models ...