Closed neohotsauce closed 1 year ago
It works if select option is removed from the virtual. Works if the virtual is as below:
AddressSchema.virtual("residentials", {
ref: "Citizen",
localField: "_id",
foreignField: "permanentAddress.address",
justOne: false,
autopopulate: true,
match: {
status: "active"
}
});
The virtual is not autopopulated while the document property is.
const mongoose = require('mongoose');
const AddressSchema = new mongoose.Schema(
{
name: {
type: String
},
status: {
type: String,
enum: ["active", "inactive"],
default: "active"
}
},
{
timestamps: true,
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
AddressSchema.virtual("residentials", {
ref: "Citizen",
localField: "_id",
foreignField: "permanentAddress.address",
justOne: false,
autopopulate: true,
match: {
status: "active"
},
options: {
select:
"name nId"
}
});
AddressSchema.plugin(require("mongoose-autopopulate"));
const CitizenSchema = new mongoose.Schema(
{
nId: {
type: String,
unique: true,
required: [true, "Please add national ID card"]
},
name: {
type: String,
required: [true, "Please add a name"],
trim: true
},
permanentAddress: {
name: {
type: String,
trim: true
},
address: {
type: mongoose.Schema.ObjectId,
ref: "Address"
},
},
father: {
type: mongoose.Schema.ObjectId,
refPath: "fatherType",
autopopulate: true
},
fatherType: {
type: String,
enum: ["Citizen", "Guest"],
required: true
},
status: {
type: String,
enum: ["active", "inactive"],
default: "active"
}
},
{
timestamps: true,
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
CitizenSchema.plugin(require("mongoose-autopopulate"));
const Address = mongoose.model('Address', AddressSchema);
const Citizen = mongoose.model('Citizen', CitizenSchema);
async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
const entry = await Address.create({
name: "Another name for The Address",
status: "active"
});
const doc = await Citizen.create({
nId: 'Hello',
name: 'There',
permanentAddress: {
name: 'The Address',
address: entry._id
},
fatherType: "Guest"
});
const res = await Citizen.create({
nId: 'Yo',
name: 'Test',
permanentAddress: {
name: "The Address",
address: entry._id
},
father: doc._id,
fatherType: "Citizen",
status: "active"
});
console.log(await Citizen.find());
console.log(await Address.findOne())
}
run();
Output:
[
{
permanentAddress: {
name: 'The Address',
address: new ObjectId("63bc67003be77fc70e511bff")
},
_id: new ObjectId("63bc67003be77fc70e511c02"),
nId: 'Hello',
name: 'There',
fatherType: 'Guest',
status: 'active',
createdAt: 2023-01-09T19:12:00.278Z,
updatedAt: 2023-01-09T19:12:00.278Z,
__v: 0,
id: '63bc67003be77fc70e511c02'
},
{
permanentAddress: {
name: 'The Address',
address: new ObjectId("63bc67003be77fc70e511bff")
},
_id: new ObjectId("63bc67003be77fc70e511c04"),
nId: 'Yo',
name: 'Test',
father: {
permanentAddress: [Object],
_id: new ObjectId("63bc67003be77fc70e511c02"),
nId: 'Hello',
name: 'There',
fatherType: 'Guest',
status: 'active',
createdAt: 2023-01-09T19:12:00.278Z,
updatedAt: 2023-01-09T19:12:00.278Z,
__v: 0,
id: '63bc67003be77fc70e511c02'
},
fatherType: 'Citizen',
status: 'active',
createdAt: 2023-01-09T19:12:00.305Z,
updatedAt: 2023-01-09T19:12:00.305Z,
__v: 0,
id: '63bc67003be77fc70e511c04'
}
]
{
_id: new ObjectId("63bc67003be77fc70e511bff"),
name: 'Another name for The Address',
status: 'active',
createdAt: 2023-01-09T19:12:00.233Z,
updatedAt: 2023-01-09T19:12:00.233Z,
__v: 0,
residentials: [
{
permanentAddress: [Object],
_id: new ObjectId("63bc67003be77fc70e511c02"),
nId: 'Hello',
name: 'There',
id: '63bc67003be77fc70e511c02'
},
{
permanentAddress: [Object],
_id: new ObjectId("63bc67003be77fc70e511c04"),
nId: 'Yo',
name: 'Test',
father: new ObjectId("63bc67003be77fc70e511c02"),
id: '63bc67003be77fc70e511c04'
}
],
id: '63bc67003be77fc70e511bff'
}
I took a closer look and the issue is that Mongoose's selectPopulatedFields
helper only adds the fields being populated to the projection. It also needs to add the field referenced by refPath
to the projection.
As a workaround, you can add fatherType
to the projection: select: "name nId fatherType"
Fix will be in Mongoose 7.4.4.
I am autopopulating a virtual field and the populated documents have a field with refPath. However the field with refPath is not autopopulated. The same field is autopopulated if refPath is replaced with ref.
Schema with the virtual:
I am autopopulating residentials as a virtual and the populated documents have the below schema.
Schema of the virtually populated documents:
The father field is not autopopulated with refPath but is autopopulated when replaced with ref.