Mongoose: Can't push discriminator fields in embedded array

Created on 22 Feb 2017  路  5Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When pushing new elements in base model, discriminator fields are ignored. Is it a bug, a misunderstanding, or an unimplemented feature ?

If the current behavior is a bug, please provide the steps to reproduce.
I just extended the doc example :

var Schema = mongoose.Schema;

    var eventSchema = new Schema({ message: String },
      { discriminatorKey: 'kind', _id: false });

    var batchSchema = new Schema({ events: [eventSchema] });

    // `batchSchema.path('events')` gets the mongoose `DocumentArray`
    var docArray = batchSchema.path('events');

    // The `events` array can contain 2 different types of events, a
    // 'clicked' event that requires an element id that was clicked...
    var Clicked = docArray.discriminator('Clicked', new Schema({
      element: {
        type: String,
        required: true
      }
    }, { _id: false }));


    // ... and a 'purchased' event that requires the product that was purchased.
    var Purchased = docArray.discriminator('Purchased', new Schema({
      product: {
        type: String,
        required: true
      }
    }, { _id: false }));

    var Batch = db.model('EventBatch', batchSchema);

    // Create a new batch of events with different kinds
    var batch = {
      events: [      
        { kind: 'Purchased', product: 'action-figure-1' }
      ]
    };

    Batch.create(batch).then(function(doc) {

      return Batch.update({_id : doc._id},
      {
        '$push': { 'events': { kind: 'Clicked', element: '#hero' } }
      })

    })

With logs :

Mongoose: eventbatches.insert({ _id: ObjectId("58ae0896207bb409d8c28f2e"), events: [ { product: 'action-figure-1', kind: 'Purchased' } ], __v: 0 })
Mongoose: eventbatches.update({ _id: ObjectId("58ae0896207bb409d8c28f2e") }, { '$push': { events: [ {} ] } }, {})

What is the expected behavior?
Adding a new item with discriminator fields.

On mongoose 4.8.4
Mongodb v3.0.0
Nodejs
v4.4.5

needs clarification

Most helpful comment

I'm experiencing this same bug with findOneAndUpdate too.

Actually, only the properties defined at the eventSchema level are written to the db. The discriminator key kind and all the fields specific to the ClickedEvent or PurchasedEvent are lost.

This bug is still there in 4.8.5.

All 5 comments

Aren't you trying to make the discriminator model inherit from eventSchema though? Maybe I'm not understanding what you're trying to do. It's not docArray but eventSchema that should be calling .discriminator()

Well, as I said, it's just the doc example for embedded array discriminator. You can find it right here : http://mongoosejs.com/docs/discriminators.html.

According to the doc, I understand that the difference between external model discriminator and embedded array discriminator is exactly to create discriminator on docArray :

Embedded discriminators are different because the different discriminator types are stored in the same document array (within a document) rather than the same collection

By the way, I read someone with the same issue in the comments of a 4.8 mongoose blog article : http://thecodebarbarian.com/mongoose-4.8-embedded-discriminators.html

Thanks for your reply !

I'm experiencing this same bug with findOneAndUpdate too.

Actually, only the properties defined at the eventSchema level are written to the db. The discriminator key kind and all the fields specific to the ClickedEvent or PurchasedEvent are lost.

This bug is still there in 4.8.5.

I have the same problem reported by @davebaol
Referring to the Embedded Discriminator Blog, the following code logs only the properties at the eventSchema level for the pushed event:

javascript function testFindOneAndUpdate(batchModel) { const newBatch = { events: [ { kind: 'Clicked', element: 'Test', message: "click1"}, { kind: 'Purchased', product: 22, message: "purchase1" } ] }; batchModel.create(newBatch) .then(function(batch) { var data = { kind: 'Purchased', product: 33, message: "purchase2" }; return batchModel.findOneAndUpdate( { '_id': batch._id }, { $push: { events: { $each: [ data ], $position: 0 } } }, { 'new': true } )}) .then(batch => { console.log(JSON.stringify(batch.events)); }) }

Thanks for the fix @vkarpov15
I can confirm that 4.8.7 works fine for the typical simple case { $push: { events: { kind: 'Clicked', element: '#hero' } } } :+1:
However, it still fails for slightly more complex cases like { $push: { events: { $each: { kind: 'Clicked', element: '#hero' }, $position: 0 } } } :disappointed:

Should I open a new issue?

Was this page helpful?
0 / 5 - 0 ratings