briankircho/mongoose-schema-extend

When saving a model with an embedded document array of a base type, any fields present only in the derived types do not get saved

Opened this issue · 11 comments

Going off of the example currently in the readme, let's say you have a base PersonSchema, and a derived EmployeeSchema which adds the department field:

var PersonSchema = new Schema({
    name : String
}, { collection : 'users' });

var EmployeeSchema = PersonSchema.extend({
    department : String
});

var Person = mongoose.model('Person', PersonSchema),
    Employee = mongoose.model('Employee', EmployeeSchema);

Now let's add a third schema into the mix which has a field people that holds an array of embedded documents of type PersonSchema:

var ContactListSchema = new Schema({
    people: [PersonSchema]
});
var ContactList = mongoose.model('ContactList', ContactListSchema);

Let's create a contact list and add some people in it - in this example, they're both employees:

var myContactList = new ContactList();

myContactList.people.push(new Employee({
    name : 'Brian Kirchoff',
    department : 'Engineering'
}));

myContactList.people.push(new Employee({
    name : 'John Doe',
    department : 'Marketing'
}));

myContactList.save(function (err) { if (err) throw err; });

If you examine the database now, you'll notice that the department field did not get saved for either person - only the name was saved:

    > db.contactlists.find({}).pretty()
    {
            "_id" : ObjectId("532504422740912422289cf4"),
            "people" : [
                    {
                            "_id" : ObjectId("532504422740912422289cf5"),
                            "name" : "Brian Kirchoff"
                    },
                    {
                            "_id" : ObjectId("532504422740912422289cf6"),
                            "name" : "John Doe"
                    }
            ],
            "__v" : 0
    }

I'm not sure exactly why it's happening - I thought it might be because Mongoose is stripping out any fields that aren't part of the PersonSchema due to the strict option (enabled by default), but disabling it didn't seem to have any effect. The only workaround I've found is to use the Mixed schema type when defining ContactListSchema:

var ContactListSchema = new Schema({
    people: [Schema.Types.Mixed]
});

With this change, the department field gets saved properly.

Here's a complete test file that combines all the above snippets and also adds some expectations:

var mongoose = require('mongoose'),
    extend = require('mongoose-schema-extend'),
    expect = require('chai').expect;
var Schema = mongoose.Schema;

mongoose.connect("localhost:27017/test");

var PersonSchema = new Schema({
    name : String
}, { collection : 'users' });

var EmployeeSchema = PersonSchema.extend({
    department : String
});

var ContactListSchema = new Schema({
    people: [Schema.Types.Mixed]
});

var Person = mongoose.model('Person', PersonSchema),
    Employee = mongoose.model('Employee', EmployeeSchema),
    ContactList = mongoose.model('ContactList', ContactListSchema);

var myContactList = new ContactList();

myContactList.people.push(new Employee({
    name : 'Brian Kirchoff',
    department : 'Engineering'
}));

myContactList.people.push(new Employee({
    name : 'John Doe',
    department : 'Marketing'
}));

myContactList.save(function (err) {
    if (err) throw err;

    expect(myContactList.people[0].name).to.equal('Brian Kirchoff');
    expect(myContactList.people[0].department).to.equal('Engineering');
    expect(myContactList.people[1].name).to.equal('John Doe');
    expect(myContactList.people[1].department).to.equal('Marketing');

    console.log('All expectations succeeded.');
    process.exit();
});

This requires the following:

npm install mongoose mongoose-schema-extend chai

Let me know if this behavior is by design, or if there is something else I'm supposed to do to use this library correctly.

I've tried this with mongoose v3.8.8, and mongoose-schema-extend v0.1.7.

We're hitting the same issue.

Hi there.

I'm facing the same issue. I would like polymorphism inside an array.
Has anyone found a not ugly solution/workaround?

+1

Have you tried this with the discriminatorKey option also? Can't seem to get mine to save the discriminatorKey. Will have to implement it manually if this doesn't work

+1 We also need to have polymorphism within an array of subdocuments. When I use the base schema as the type in the array definition, none of the fields in the extended schemas are saved. When I use a mixed schema type, the _type discriminator key does not get saved.

Has someone already found a solution ???

I will check it, if anyone have solved it, please, let me know

fubhy commented

@sieira Any progress on this?