Skip to content

Commit

Permalink
fix(discriminators): remove fields not selected in child when queryin…
Browse files Browse the repository at this point in the history
…g by base model

Fix #4991
  • Loading branch information
vkarpov15 committed Feb 21, 2017
1 parent ff00606 commit 9921d15
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 8 deletions.
7 changes: 7 additions & 0 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,13 @@ function init(self, obj, doc, prefix) {
path = prefix + i;
schema = self.schema.path(path);

// Should still work if not a model-level discriminator, but should not be
// necessary. This is *only* to catch the case where we queried using the
// base model and the discriminated model has a projection
if (self.schema.$isRootDiscriminator && !self.isSelected(path)) {
return;
}

if (!schema && utils.isObject(obj[i]) &&
(!obj[i].constructor || utils.getFunctionName(obj[i].constructor) === 'Object')) {
// assume nested object
Expand Down
2 changes: 2 additions & 0 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ Model.discriminator = function(name, schema) {
_name = name;
}

schema.$isRootDiscriminator = true;

this.discriminators[_name] = this.db.model(name, schema, this.collection.name);
var d = this.discriminators[_name];
d.prototype.__proto__ = this.prototype;
Expand Down
5 changes: 4 additions & 1 deletion lib/queryhelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ exports.createModel = function createModel(model, doc, fields) {
: null;

if (key && doc[key] && model.discriminators && model.discriminators[doc[key]]) {
return new model.discriminators[doc[key]](undefined, fields, true);
var discriminator = model.discriminators[doc[key]];
var _fields = utils.clone(fields);
exports.applyPaths(_fields, discriminator.schema);
return new model.discriminators[doc[key]](undefined, _fields, true);
}

return new model(undefined, fields, true);
Expand Down
22 changes: 15 additions & 7 deletions lib/schema/documentarray.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,18 +338,26 @@ function scopePaths(array, fields, init) {
return undefined;
}

var path = array.path + '.',
keys = Object.keys(fields),
i = keys.length,
selected = {},
hasKeys,
key;
var path = array.path + '.';
var keys = Object.keys(fields);
var i = keys.length;
var selected = {};
var hasKeys;
var key;
var sub;

while (i--) {
key = keys[i];
if (key.indexOf(path) === 0) {
sub = key.substring(path.length);
if (sub === '$') {
continue;
}
if (sub.indexOf('$.') === 0) {
sub = sub.substr(2);
}
hasKeys || (hasKeys = true);
selected[key.substring(path.length)] = fields[key];
selected[sub] = fields[key];
}
}

Expand Down
1 change: 1 addition & 0 deletions test/schema.select.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ describe('schema select option', function() {
assert.equal(s.isSelected('thin'), true);
assert.equal(s.isSelected('docs.name'), false);
assert.equal(s.isSelected('docs.bool'), true);
assert.ok(s.isSelected('docs'));
assert.strictEqual(undefined, s.name);
assert.strictEqual(undefined, s.docs[0].name);
assert.equal(s.thin, true);
Expand Down

0 comments on commit 9921d15

Please sign in to comment.