Skip to content

Commit ad4462c

Browse files
committed
Merge pull request #2773 from chetverikov/gh2719
Fix #2719
2 parents 5cf9fd4 + 80f8332 commit ad4462c

File tree

2 files changed

+113
-51
lines changed

2 files changed

+113
-51
lines changed

lib/model.js

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,12 +2182,7 @@ var excludeIdReg = /\s?-_id\s?/,
21822182
excludeIdRegGlobal = /\s?-_id\s?/g;
21832183

21842184
function populate(model, docs, options, cb) {
2185-
var schema = model._getSchema(options.path),
2186-
modelsMap, rawIds;
2187-
2188-
if (schema && schema.caster) {
2189-
schema = schema.caster;
2190-
}
2185+
var modelsMap, rawIds;
21912186

21922187
// normalize single / multiple docs passed
21932188
if (!Array.isArray(docs)) {
@@ -2198,7 +2193,7 @@ function populate(model, docs, options, cb) {
21982193
return cb();
21992194
}
22002195

2201-
modelsMap = getModelsMapForPopulate(model, schema, docs, options);
2196+
modelsMap = getModelsMapForPopulate(model, docs, options);
22022197
rawIds = getIdsForAndAddIdsInMapPopulate(modelsMap);
22032198

22042199
var i, len = modelsMap.length,
@@ -2294,65 +2289,91 @@ function populate(model, docs, options, cb) {
22942289
}
22952290
}
22962291

2297-
function getModelsMapForPopulate(model, schema, docs, options) {
2292+
function getModelsMapForPopulate(model, docs, options) {
22982293
var i, doc, len = docs.length,
2299-
available = {}, map = [],
2300-
refPath = schema && schema.options && schema.options.refPath,
2301-
Model, currentOptions, modelNames, modelName;
2294+
available = {},
2295+
map = [],
2296+
modelNameFromQuery = options.model && options.model.modelName || options.model,
2297+
schema, refPath, Model, currentOptions, modelNames, modelName, discriminatorKey, modelForFindSchema;
23022298

2303-
if (refPath) {
2304-
for (i = 0; i < len; i++) {
2305-
doc = docs[i];
2299+
schema = model._getSchema(options.path);
2300+
2301+
if(schema && schema.caster){
2302+
schema = schema.caster;
2303+
}
2304+
2305+
if (!schema && model.discriminators){
2306+
discriminatorKey = model.schema.discriminatorMapping.key
2307+
}
2308+
2309+
refPath = schema && schema.options && schema.options.refPath;
2310+
2311+
for (i = 0; i < len; i++) {
2312+
doc = docs[i];
2313+
2314+
if(refPath){
23062315
modelNames = utils.getValue(refPath, doc);
2316+
}else{
2317+
if(!modelNameFromQuery){
2318+
var schemaForCurrentDoc;
23072319

2308-
if (!modelNames)
2309-
continue;
2320+
if(!schema && discriminatorKey){
2321+
modelForFindSchema = utils.getValue(discriminatorKey, doc);
23102322

2311-
if (!Array.isArray(modelNames)) {
2312-
modelNames = [modelNames];
2313-
}
2323+
if(modelForFindSchema){
2324+
schemaForCurrentDoc = model.db.model(modelForFindSchema)._getSchema(options.path);
23142325

2315-
var k = modelNames.length;
2316-
while (k--) {
2317-
modelName = modelNames[k];
2318-
if (!available[modelName]) {
2319-
Model = model.db.model(modelName);
2320-
currentOptions = {
2321-
model: Model
2322-
};
2323-
2324-
utils.merge(currentOptions, options);
2325-
2326-
available[modelName] = {
2327-
Model: Model,
2328-
options: currentOptions,
2329-
docs: [doc],
2330-
ids: []
2331-
};
2332-
map.push(available[modelName]);
2326+
if(schema && schema.caster){
2327+
schema = schema.caster;
2328+
}
2329+
}
23332330
} else {
2334-
available[modelName].docs.push(doc);
2331+
schemaForCurrentDoc = schema;
23352332
}
23362333

2334+
modelNames = [
2335+
schemaForCurrentDoc && schemaForCurrentDoc.options && schemaForCurrentDoc.options.ref // declared in schema
2336+
|| model.modelName // an ad-hoc structure
2337+
]
2338+
}else{
2339+
modelNames = [modelNameFromQuery]; // query options
23372340
}
23382341
}
23392342

2340-
} else {
2343+
if (!modelNames)
2344+
continue;
23412345

2342-
// model name for the populate query
2343-
modelName = options.model && options.model.modelName || options.model // query options
2344-
|| schema && schema.options && schema.options.ref // declared in schema
2345-
|| model.modelName; // an ad-hoc structure
2346+
if (!Array.isArray(modelNames)) {
2347+
modelNames = [modelNames];
2348+
}
23462349

2347-
Model = model.db.model(modelName);
2348-
options.model = Model;
2350+
var k = modelNames.length;
2351+
while (k--) {
2352+
modelName = modelNames[k];
2353+
if (!available[modelName]) {
2354+
Model = model.db.model(modelName);
2355+
currentOptions = {
2356+
model: Model
2357+
};
2358+
2359+
if(schema && !discriminatorKey){
2360+
options.model = Model;
2361+
}
23492362

2350-
map = [{
2351-
Model: Model,
2352-
options: options,
2353-
docs: docs,
2354-
ids: []
2355-
}];
2363+
utils.merge(currentOptions, options);
2364+
2365+
available[modelName] = {
2366+
Model: Model,
2367+
options: currentOptions,
2368+
docs: [doc],
2369+
ids: []
2370+
};
2371+
map.push(available[modelName]);
2372+
} else {
2373+
available[modelName].docs.push(doc);
2374+
}
2375+
2376+
}
23562377
}
23572378

23582379
return map;

test/model.discriminator.querying.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,47 @@ describe('model', function() {
705705
});
706706
});
707707
});
708+
709+
it('reference in child schemas (gh-2719)', function(done){
710+
var vehicleSchema = new Schema({});
711+
var carSchema = new Schema({
712+
speed: Number,
713+
garage: {type: Schema.Types.ObjectId, ref: 'gh2719PopulationGarage'}
714+
});
715+
var busSchema = new Schema({
716+
speed: Number,
717+
garage: {type: Schema.Types.ObjectId, ref: 'gh2719PopulationGarage'}
718+
});
719+
720+
var garageSchema = new Schema({
721+
name: String,
722+
num_of_places: Number
723+
});
724+
725+
var Vehicle = db.model('gh2719PopulationVehicle', vehicleSchema)
726+
, Car = Vehicle.discriminator('gh2719PopulationCar', carSchema)
727+
, Bus = Vehicle.discriminator('gh2719PopulationBus', busSchema)
728+
, Garage = db.model('gh2719PopulationGarage', garageSchema);
729+
730+
Garage.create({name: 'My', num_of_places: 3}, function(err, garage){
731+
assert.ifError(err);
732+
Car.create({ speed: 160, garage: garage }, function(err, car) {
733+
assert.ifError(err);
734+
Bus.create({ speed: 80, garage: garage }, function(err, bus) {
735+
assert.ifError(err);
736+
Vehicle.find({}).populate('garage').exec(function(err, vehicles){
737+
assert.ifError(err);
738+
739+
vehicles.forEach(function(v){
740+
assert.ok(v.garage instanceof Garage);
741+
});
742+
743+
done();
744+
});
745+
})
746+
});
747+
});
748+
})
708749
});
709750

710751
describe('aggregate', function() {

0 commit comments

Comments
 (0)