Skip to content

Commit 96aad77

Browse files
committed
mongoose populate
1 parent 4ac5a50 commit 96aad77

File tree

1 file changed

+71
-1
lines changed

1 file changed

+71
-1
lines changed

MongoDB/populate-method-mongoose-referencing-other-model.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function getUserWithPosts(username) {
103103

104104
And like magic, we have created a unified object using 2 schemas, 2 models, and 2 collections. All of the steps are important of course, but the thing that no other site made explicitly clear was that after setting up the ground work, you have to make sure you are pushing \_ids into the field you will need populated later.
105105

106-
### Another implementation
106+
### 2nd Implementation
107107

108108
Let’s pretend we’re building a social app, and we have two models: a User and a Post:
109109

@@ -123,6 +123,76 @@ var PostSchema = {
123123
124124
If you run this query: `Post.find({}).populate('user').exec(callback)`, Mongoose will look at the field user in the post, see that it has a ref to the User model, and find that user by its \_id
125125
126+
### 3rd Implementation in my DevBook Repo
127+
128+
In Profile model, I have the the 'user' property as ObjectId like below,
129+
130+
```js
131+
const ProfileSchema = new Schema({
132+
user: {
133+
type: Schema.Types.ObjectId,
134+
ref: 'users'
135+
},
136+
handle: {
137+
type: String,
138+
required: true,
139+
max: 40
140+
},
141+
---
142+
---
143+
});
144+
145+
module.exports = Profile = mongoose.model('profile', ProfileSchema);
146+
```
147+
148+
And in my Profile routes I have the following API endpoint
149+
150+
```js
151+
router.get(
152+
'/',
153+
passport.authenticate('jwt', { session: false }),
154+
(req, res) => {
155+
const errors = {}; // just like in user route, I want to append to the errors object for any actual errors that will be generated. And returning that object for the error case
156+
157+
Profile.findOne({ user: req.user.id })
158+
.populate('user', ['name', 'avatar'])
159+
.then(profile => {
160+
if (!profile) {
161+
errors.noprofile = 'There is not profile for this user';
162+
return res.status(404).json(errors);
163+
}
164+
res.json(profile);
165+
})
166+
.catch(err => res.status(404).json(err));
167+
}
168+
)
169+
```
170+
In the above A) I am populating my user's profile using the query builder. http://mongoosejs.com/docs/populate.html#population
171+
172+
B) The first parameter of .populate() is the model you wish to use for population. If not specified, populate will look up the model by the name in the Schema's 'ref' field.
173+
http://mongoosejs.com/docs/api.html#query_Query-populate
174+
175+
C) The second parameter to .populate() is the Field selection for the population query. So here, I only wanted to show the name and avatar of the current logged-in user. So, I pass, ['name', 'avatar']
176+
177+
D) Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). So, when I do the below
178+
179+
Profile.findOne({ user: req.user.id })
180+
.populate('user', ['name', 'avatar'])
181+
182+
Populated paths are no longer set to their original _id , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results.
183+
(http://mongoosejs.com/docs/populate.html)
184+
185+
E) .populate() needs a query to attach itself to, so we are using Profile.findOne() to find a profile who matches the id I provide in the argument. This returns our user document. This is when .populate() takes over.
186+
187+
F) Flow of .populate() -> After findOne() finds the req.user.id and assigns it to the variable 'user' > .populate() is called on user, it will go to the appropriate collection (user model in this case) , search for that _ids, and return my user with 'name' and 'avatar'
188+
189+
G) Why I can fetch user's model data with below line from profile route.
190+
191+
Profile.findOne({ user: req.user.id })
192+
.populate('user', ['name', 'avatar'])
193+
194+
Because - In Profile model, I have the the 'user' property as ObjectId
195+
126196
### Sources to read
127197
128198
[https://medium.com/@nicknauert/mongooses-model-populate-b844ae6d1ee7](https://mongoosejs.com/docs/2.7.x/docs/populate.html)

0 commit comments

Comments
 (0)