I have a company model which looks like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CompanySchema = new Schema(
{
companyName: String,
settings: {
type: {
priceVisible: Boolean,
allowPickupAddressAddition: Boolean,
paymentMethodsAvailable: [
{ type: Schema.Types.ObjectId, ref: "PaymentMethod" },
],
},
},
}
);
const Company = mongoose.model("Company", CompanySchema);
module.exports = Company;
And I want to populate the values store in paymentMethodsAvailable
array. Here is relevant controller code:
const company = await Company.findOne({ _id: id }).populate([
{
path: "settings",
populate: [{path: "paymentMethodsAvailable"}]
},
]);
But this doesn't work as expected. I can see that it might be trying to populate settings object, and fails there. Is there a way in which I can tell mongoose to populate settings.paymentMethodsAvailable
?
You should notice The type
Key:
type
is a special property in Mongoose schemas. When Mongoose finds a nested property named type in your schema, Mongoose assumes that it needs to define aSchemaType
with the given type.
type
is a nested property of settings
, the Mongoose schema should be:const CompanySchema = new mongoose.Schema({
companyName: String,
settings: {
type: {
type: {
priceVisible: Boolean,
paymentMethodsAvailable: [{ type: mongoose.Schema.Types.ObjectId, ref: 'PaymentMethod' }],
},
},
},
});
// seed
const [p1] = await PaymentMethod.create([{ name: 'a' }, { name: 'b' }]);
const [c1] = await Company.create([
{
companyName: 'c-a',
settings: {
type: {
priceVisible: true,
paymentMethodsAvailable: [p1],
},
},
},
]);
// populate
const company = await Company.findOne({ _id: c1?._id }).populate('settings.type.paymentMethodsAvailable');
console.log(util.inspect(company?.toObject(), false, null));
The populate path is settings.type.paymentMethodsAvailable
.
Output:
{
settings: {
type: {
priceVisible: true,
paymentMethodsAvailable: [
{
_id: new ObjectId("64abce807233874fe5733d10"),
name: 'a',
__v: 0
}
],
_id: new ObjectId("64abce807233874fe5733d15")
}
},
_id: new ObjectId("64abce807233874fe5733d14"),
companyName: 'c-a',
__v: 0
}
type
is not a nested property of settings
, the Mongoose schema is like yours:const CompanySchema = new mongoose.Schema({
companyName: String,
settings: {
type: {
priceVisible: Boolean,
paymentMethodsAvailable: [{ type: mongoose.Schema.Types.ObjectId, ref: 'PaymentMethod' }],
},
},
});
// seed
const [p1] = await PaymentMethod.create([{ name: 'a' }, { name: 'b' }]);
const [c1] = await Company.create([
{
companyName: 'c-a',
settings: {
priceVisible: true,
paymentMethodsAvailable: [p1],
},
},
]);
// populate
const company = await Company.findOne({ _id: c1?._id }).populate('settings.paymentMethodsAvailable');
console.log(util.inspect(company?.toObject(), false, null));
The populate path is settings.paymentMethodsAvailable
.
Output:
{
_id: new ObjectId("64abd00acd28f4120a317c2e"),
companyName: 'c-a',
settings: {
priceVisible: true,
paymentMethodsAvailable: [
{
_id: new ObjectId("64abd00acd28f4120a317c2a"),
name: 'a',
__v: 0
}
],
_id: new ObjectId("64abd00acd28f4120a317c2f")
},
__v: 0
}