Skip to content

Commit

Permalink
fix(populate): allow using options: { strictPopulate: false } to di…
Browse files Browse the repository at this point in the history
…sable strict populate

Re: #13863
  • Loading branch information
vkarpov15 committed Oct 20, 2023
1 parent 1eee4f8 commit 967912f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 93 deletions.
3 changes: 2 additions & 1 deletion lib/helpers/populate/getModelsMapForPopulate.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
let allSchemaTypes = getSchemaTypes(model, modelSchema, null, options.path);
allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);

if (allSchemaTypes.length === 0 && options.strictPopulate !== false && options._localModel != null) {
const isStrictPopulateDisabled = options.strictPopulate === false || options.options?.strictPopulate === false;
if (!isStrictPopulateDisabled && allSchemaTypes.length === 0 && options._localModel != null) {
return new StrictPopulate(options._fullPath || options.path);
}

Expand Down
131 changes: 39 additions & 92 deletions test/model.populate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10331,117 +10331,64 @@ describe('model: populate:', function() {

describe('strictPopulate', function() {
it('does not throw an error when using strictPopulate on a nested path (gh-13863)', async function() {
const testSchema = new mongoose.Schema({
name: String,
location: String,
occupation: String
const l4Schema = new mongoose.Schema({
name: String
});

const ASchema = new mongoose.Schema({
name: String,
age: Number,
weight: Number,
dModel: {
type: 'ObjectId',
ref: 'gh13863DModel'
},
fModel: {
const l3aSchema = new mongoose.Schema({
l4: {
type: 'ObjectId',
ref: 'gh13863FModel'
ref: 'L4'
}
});
const l3bSchema = new mongoose.Schema({
otherProp: String
});

const XSchema = new mongoose.Schema({
name: String,
car: String,
make: String,
model: String,
aModel: {
type: 'ObjectId',
ref: 'gh13863AModel'
},
testModel: {
const l2Schema = new mongoose.Schema({
l3a: {
type: 'ObjectId',
ref: 'gh13863Test'
ref: 'L3A'
},
cModel: {
l3b: {
type: 'ObjectId',
ref: 'gh13863CModel'
ref: 'L3B'
}
});

const CSchema = new Schema({
name: String,
hobbies: String
});

const DSchema = new Schema({
name: String
});

const FSchema = new Schema({
name: String
});

const GSchema = new Schema({
name: String
});

const Test = db.model('gh13863Test', testSchema);
const AModel = db.model('gh13863AModel', ASchema);
const XModel = db.model('gh13863XModel', XSchema);
const CModel = db.model('gh13863CModel', CSchema);
const DModel = db.model('gh13863DModel', DSchema);
const FModel = db.model('gh13863FModel', FSchema);
const GModel = db.model('gh13863GModel', GSchema);

await GModel.create({
name: 'G-Man'
});
const dDoc = await DModel.create({
name: 'Dirty Dan'
});

const fDoc = await FModel.create({
name: 'Filthy Frank'
});

const testDoc = await Test.create({
name: 'Test Testserson',
location: 'Florida',
occupation: 'Tester'
});

const aDoc = await AModel.create({
name: 'A-men',
age: 4,
weight: 404,
dModel: dDoc._id,
fModel: fDoc._id
const l1Schema = new mongoose.Schema({
l2: {
type: 'ObjectId',
ref: 'L2'
}
});

const cDoc = await CModel.create({
name: 'C-ya',
hobbies: 'Leaving'
});
const L1 = db.model('L1', l1Schema);
const L2 = db.model('L2', l2Schema);
const L3A = db.model('L3A', l3aSchema);
const L3B = db.model('L3B', l3bSchema);
const L4 = db.model('L4', l4Schema);

await XModel.create({
name: 'XCOM',
aModel: aDoc._id,
cModel: cDoc._id,
testModel: testDoc._id
});
const { _id: l4 } = await L4.create({ name: 'test l4' });
const { _id: l3a } = await L3A.create({ l4 });
const { _id: l3b } = await L3B.create({ name: 'test l3' });
const { _id: l2 } = await L2.create({ l3a, l3b });
const { _id: l1 } = await L1.create({ l2 });

const res = await XModel.find().populate({
path: 'aModel testModel cModel',
const res = await L1.findById(l1).populate({
path: 'l2',
populate: {
path: 'dModel fModel',
populate: 'gModel',
strictPopulate: false
path: 'l3a l3b',
populate: {
path: 'l4',
options: {
strictPopulate: false
}
}
}
});

assert.ok(res);
assert.equal(res.l2.l3a.l4.name, 'test l4');
assert.equal(res.l2.l3b.l4, undefined);
});
it('reports full path when throwing `strictPopulate` error with deep populate (gh-10923)', async function() {
const L2 = db.model('Test', new Schema({ name: String }));
Expand Down

0 comments on commit 967912f

Please sign in to comment.