Skip to content

Commit

Permalink
Merge pull request #11177 from aleksadjukic/patch-2
Browse files Browse the repository at this point in the history
Update docs to include the section about populating multiple paths in middleware
  • Loading branch information
vkarpov15 committed Jan 9, 2022
2 parents 93a3fca + 2a5292e commit dff2d49
Showing 1 changed file with 36 additions and 0 deletions.
36 changes: 36 additions & 0 deletions docs/populate.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ user and have a good reason for doing so.
<li><a href="#count">Populate Virtuals: The Count Option</a></li>
<li><a href="#populating-maps">Populating Maps</a></li>
<li><a href="#populate-middleware">Populate in Middleware</a></li>
<li><a href="#populating-multiple-paths-middleware">Populating Multiple Paths in Middleware</a></li>
</ul>

<h3 id="saving-refs"><a href="#saving-refs">Saving refs</a></h3>
Expand Down Expand Up @@ -804,6 +805,41 @@ MySchema.post('save', function(doc, next) {
});
```

<h3 id="populating-multiple-paths-middleware"><a href="#populating-multiple-paths-middleware">Populating Multiple Paths in Middleware</a></h3>

Populating multiple paths in middleware can be helpful when you always want to populate some fields. But, the implementation is just a tiny bit trickier than what you may think. Here's how you may expect it to work:

```javascript
const userSchema = new Schema({
email: String,
password: String,
followers: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
following: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }]
})

userSchema.pre('find', function (next) {
this.populate("followers following");
next();
});

const User = mongoose.model('User', userSchema)
```

However, this will not work. By default, passing multiple paths to `populate()` in the middleware will trigger an infinite recursion, which means that it will basically trigger the same middleware for all of the paths provided to the `populate()` method - For example, `this.populate('followers following')` will trigger the same middleware for both `followers` and `following` fields and the request will just be left hanging in an infinite loop.

To avoid this, we have to add the `_recursed` option, so that our middleware will avoid populating recursively. The example below will make it work as expected.

```javascript
userSchema.pre('find', function (next) {
if (this.options._recursed) {
return next();
}
this.populate({ path: "followers following", options: { _recursed: true } });
next();
});
```
Alternatively, you can check out the [mongoose-autopopulate plugin](http://npmjs.com/package/mongoose-autopopulate).

### Next Up

Now that we've covered `populate()`, let's take a look at [discriminators](/docs/discriminators.html).

0 comments on commit dff2d49

Please sign in to comment.