Skip to content

Commit

Permalink
test(populate): repro #5970
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Jan 21, 2018
1 parent 07feb5a commit ac2c662
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 0 deletions.
115 changes: 115 additions & 0 deletions lib/services/populate/getSchemaTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
'use strict';

/*!
* ignore
*/

var Mixed = require('../../schema/mixed');
var get = require('lodash.get');
var mpath = require('mpath');
var utils = require('../../utils');

/*!
* ignore
*/

module.exports = function getSchemaTypes(schema, doc, path) {
var pathschema = schema.path(path);

if (pathschema) {
return pathschema;
}

function search(parts, schema) {
var p = parts.length + 1;
var foundschema;
var trypath;

while (p--) {
trypath = parts.slice(0, p).join('.');
foundschema = schema.path(trypath);
if (foundschema) {
if (foundschema.caster) {
// array of Mixed?
if (foundschema.caster instanceof Mixed) {
return foundschema.caster;
}

var schemas = null;
if (doc != null && foundschema.schema != null && foundschema.schema.discriminators != null) {
var discriminators = foundschema.schema.discriminators;
var keys = mpath.get(trypath + '.' + foundschema.schema.options.discriminatorKey,
doc);
schemas = Object.keys(discriminators).
reduce(function(cur, discriminator) {
if (keys.indexOf(discriminator) !== -1) {
cur.push(discriminators[discriminator]);
}
return cur;
}, []);
}

// Now that we found the array, we need to check if there
// are remaining document paths to look up for casting.
// Also we need to handle array.$.path since schema.path
// doesn't work for that.
// If there is no foundschema.schema we are dealing with
// a path like array.$
if (p !== parts.length && foundschema.schema) {
var ret;
if (parts[p] === '$') {
if (p + 1 === parts.length) {
// comments.$
return foundschema;
}
// comments.$.comments.$.title
ret = search(parts.slice(p + 1), schema);
if (ret) {
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
!foundschema.schema.$isSingleNested;
}
return ret;
}

if (schemas != null && schemas.length > 0) {
ret = [];
for (var i = 0; i < schemas.length; ++i) {
var _ret = search(parts.slice(p), schemas[i]);
if (_ret) {
_ret.$isUnderneathDocArray = _ret.$isUnderneathDocArray ||
!foundschema.schema.$isSingleNested;
if (_ret.$isUnderneathDocArray) {
ret.$isUnderneathDocArray = true;
}
}
ret.push(_ret);
}
return ret;
} else {
ret = search(parts.slice(p), foundschema.schema);

if (ret) {
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
!foundschema.schema.$isSingleNested;
}

return ret;
}
}
}

return foundschema;
}
}
}

// look for arrays
var parts = path.split('.');
for (var i = 0; i < parts.length; ++i) {
if (parts[i] === '$') {
// Re: gh-5628, because `schema.path()` doesn't take $ into account.
parts[i] = '0';
}
}
return search(parts, schema);
}
75 changes: 75 additions & 0 deletions test/model.populate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5923,6 +5923,81 @@ describe('model: populate:', function() {
});
});

it('populating nested discriminator path (gh-5970)', function() {
var Author = db.model('gh5970', new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
}));

var ItemSchema = new mongoose.Schema({
title: {
type: String,
required: true
}
}, {discriminatorKey: 'type'});

var ItemBookSchema = new mongoose.Schema({
author: {
type: mongoose.Schema.ObjectId,
ref: 'gh5970'
}
});

var ItemEBookSchema = new mongoose.Schema({
author: {
type: mongoose.Schema.ObjectId,
ref: 'gh5970'
},
url: {
type: String
}
});

var BundleSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
items: [{
type: ItemSchema,
required: false
}]
});

BundleSchema.path('items').discriminator('Book', ItemBookSchema);
BundleSchema.path('items').discriminator('EBook', ItemEBookSchema);

var Bundle = db.model('gh5970_0', BundleSchema);

return Author.create({firstName: 'David', lastName: 'Flanagan'}).
then(function(author) {
return Bundle.create({
name: 'Javascript Book Collection', items: [
{type: 'Book', title: 'JavaScript: The Definitive Guide', author: author},
{
type: 'EBook',
title: 'JavaScript: The Definitive Guide Ebook',
url: 'https://google.com',
author: author
}
]
});
}).
then(function(bundle) {
return Bundle.findById(bundle._id).populate('items.author').lean();
}).
then(function(bundle) {
assert.equal(bundle.items[0].author.firstName, 'David');
assert.equal(bundle.items[1].author.firstName, 'David');
});
});

it('specify model in populate (gh-4264)', function(done) {
var PersonSchema = new Schema({
name: String,
Expand Down

0 comments on commit ac2c662

Please sign in to comment.