I'm trying to populate
array of ObjectId
in mongoose
. And inside that array, will need populate
again.
Let's say I've User
data schema as below:-
models/User.js
/** Dependencies */
// Mongoose
const mongoose = require('mongoose')
/** Data Schema */
// User Data Schema
const UserSchema = new mongoose.Schema({
// User's Name
name: {
// User's Firstname
firstName: { type: String, required: true, min: 4 },
// User's Lastname
lastName: { type: String, required: true, min: 4 }
},
// User's Address Array[ID]
address: [{
// AddressID
addressID: { type: mongoose.Schema.Types.ObjectId, ref: "Address" },
}]
})
/** Data Schema Exports */
module.exports = mongoose.model('User', UserSchema);
and Address
schema, models/Address.js
/** Dependencies */
// Mongoose
const mongoose = require('mongoose')
/** Data Schema */
// Address Data Schema
const AddressSchema = new mongoose.Schema({
// Address 1
addressOne: { type: String, required: true },
// Address 2
addressTwo: { type: String },
// Postcode
postcode: { type: String, required: true },
// City
city: { type: String, required: true },
// StateID
state: { type: mongoose.Schema.Types.ObjectId, ref: "State" },
// CountryID
country: { type: mongoose.Schema.Types.ObjectId, ref: "Country" }
})
// State Data Schema
const StateSchema = new mongoose.Schema({
// Gender's Name
name: { type: String, required: true }
})
// Country Data Schema
const CountrySchema = new mongoose.Schema({
// Race's Name
name: { type: String, required: true }
})
/** Data Schema Export */
const Address = mongoose.model('Address', AddressSchema)
const State = mongoose.model('State', StateSchema)
const Country = mongoose.model('Country', CountrySchema)
module.exports = {
Address,
State,
Country
}
I know how to populate
state
& country
from Address
, like show below:-
Address.find()
.populate('state')
.populate('country')
.then(async address => {
// do stuff
})
.catch(err => res.json({ err }))
But how can I populate
array of ObjectId
. I did the code like shown below:-
User.findById({ _id: userId }) // let's say I've the userId
.populate('address')
.then(async user => {
console.log(await user)
})
.catch(err => res.json({ err }))
Unfortunately, It returns
me something like this:-
{
"_id": "5fabababababababababab1"
"name": {
"firstName": "Lalapolalaa",
"lastName": "Newb"
},
"address": [
{
"_id": "5fcdcdcdcdcdcdcdcdc1",
"addressID": "5fefefefefefefefefef1" // should've populate (but not working)
}
],
"__v": 0
}
What I'm trying to get is like shown below:-
{
"_id": "5fabababababababababab1"
"name": {
"firstName": "Lalapolalaa",
"lastName": "Newb"
},
"address": [
{
"_id": "5fcdcdcdcdcdcdcdcdc1",
"addressID": { // populate happens here
"_id": "5fefefefefefefefefef1",
"addressOne": "Lot 1, Street 12",
"addressTwo": "SS 21",
"postcode" : "47500",
"city": "Subang Jaya",
"state": { // populate happens here
"_id": "5fghghghghghghghghg1",
"name": "Selangor",
"__v": 0
},
"country": { // populate happens here
"_id": "5ijijijijijijijijij1",
"name": "Malaysia",
"__v": 0
}
"__v": 0
}
}
],
"__v": 0
}
How can I get that (shown above) with my current code below:-
User.findById({ _id: userId }) // let's say I've the userId
.populate('address') // assuming this populate of address works
.then(async user => {
// how to populate state & country of Address?
// code below only return address[0] information (assumption)
const address = await Address.findById({ _id: user.address[0].addressID._id })
.populate('state')
.populate('country')
.then(address => address)
})
.catch(err => res.json({ err }))
I'm able to find the solution myself with below corrections:-
models/User.js
:-/** Dependencies */
// Mongoose
const mongoose = require('mongoose')
/** Data Schema */
// User Data Schema
const UserSchema = new mongoose.Schema({
// User's Name
name: {
// User's Firstname
firstName: { type: String, required: true, min: 4 },
// User's Lastname
lastName: { type: String, required: true, min: 4 }
},
// User's Address Array[ID]
address: [{ type: mongoose.Schema.Types.ObjectId, ref: "Address" }] // 1st Correction
})
/** Data Schema Exports */
module.exports = mongoose.model('User', UserSchema);
Then next I can straight code like shown below (SOLUTION):-
User.findById({ _id: userId }) // let's say I've the userId
.populate('address') // assuming this populate of address works
.then(async user => {
// create an array to hold JUST the IDs of Address available
let addressesID = []
// transfer all Address's ID
for(let i = 0; i < (user.address).length; i++) {
// push available address's ID one by one
addressesID.push(user.address[i]._id)
}
// get all address info available in Address (from DB)
const addresses = await Address.find(
{ _id: { $in: addressesID } }
)
.populate('state')
.populate('country')
.then(address => address)
})
.then(all => console.log(all))
.catch(err => res.json({ err }))
it will then console.log()
{
_id: '5fabababababababababab1',
name: {
firstName: 'Lalapolalaa',
lastName: 'Newb'
},
address: { // populate happens here
_id: '5fefefefefefefefefef1',
addressOne: 'Lot 1, Street 12',
addressTwo: 'SS 21',
postcode" : '47500',
city: 'Subang Jaya',
state: { // populate happens here
_id: '5fghghghghghghghghg1',
name: 'Selangor',
__v: 0
},
country: { // populate happens here
_id: '5ijijijijijijijijij1',
name: 'Malaysia',
__v: 0
},
__v: 0
},
__v: 0
}