Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating document with array of discriminators #8063

Closed
stoto34 opened this issue Aug 12, 2019 · 3 comments
Closed

Updating document with array of discriminators #8063

stoto34 opened this issue Aug 12, 2019 · 3 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@stoto34
Copy link

stoto34 commented Aug 12, 2019

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

It's not a bug or a feature, I just want an example for discriminators. Sorry about this post but I'm really stuck and the documentation didn't help me.

What is the current behavior?

It's not a behavior but more a request to understand how could I update a document contains 2 properties whichs are array of discriminators ? I didn't find any sample about that.

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.

Node : 10.16.1
MongoDB: 3.6.3
Mongoose: 5.6.9

const mongoose = require('mongoose');
const carSchema = require('./car');
const continentalWheelSchema = require('./wheel/continental');
const michelinWheelSchema = require('./wheel/michelin');

const CarSchema = new mongoose.Schema({}, { discriminatorKey: 'type', _id: false } );
const WheelSchema = new mongoose.Schema({}, { discriminatorKey: 'type', _id: false } );

const ClientParkSchema = new mongoose.Schema({
customer: { type: String, required: true },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
cars: [CarSchema],
wheels: [WheelSchema]
});

ClientParkSchema.path('cars').discriminator('break', carSchema);
ClientParkSchema.path('wheels').discriminator('continental', continentalWheelSchema);
ClientParkSchema.path('wheels').discriminator('michelin', michelinWheelSchema);

module.exports = {
ClientPark: mongoose.model('client_park', ClientParkSchema, 'client_park')
};

/////////////////////// CAR SCHEMA ////////////////////////

const mongoose = require('mongoose');

const CarSchema = new mongoose.Schema({
brand: { type: String, required: true },
model: { type: String, required: true },
}, { _id: false } );

module.exports = CarSchema;

/////////////////////// CONTINENTAL WHEEL SCHEMA ////////////////////////

const mongoose = require('mongoose');

const ContinentalWheelSchema = new mongoose.Schema({
model: { type: String, required: true }
}, { _id: false } );

module.exports = ContinentalWheelSchema;

/////////////////////// MICHELIN WHEEL SCHEMA ////////////////////////

const mongoose = require('mongoose');

const MichelinWheelSchema = new mongoose.Schema({
price: { type: number, required: true},
model: { type: String, required: true },
season: { type: String, required: true }
}, { _id: false } );

module.exports = MichelinWheelSchema;

my mongoose query :

clientParkModels.ClientPark.updateOne(
{
'_id': '5d39a19e2376c7089ec7707b', 'car.type': 'break', 'wheel.type': 'continental'
},
{
$set: {
'cars.$.brand': 'Ford',
'wheels.$.model': 'X5485622',
'wheels.$.price': 10000,
'wheels.$.season': 'summer'
}
}
).exec();

My document is not updated. So, I would like if I can update 2 differents discriminator in the same query ?
Could you provide an example ?

Thank you very much

@vkarpov15
Copy link
Collaborator

You might be able to do this using array filters: https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html . If not, you should just use findOne() and update the document using save()

@vkarpov15 vkarpov15 added the help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary label Aug 14, 2019
@SebT
Copy link

SebT commented Sep 25, 2019

This must be is a bug. You cannot update non-common fields on embedded array discriminators. I have the same issue.

But if you try to update one of the common fields, it works.

Example :

const slideSchema = new Schema(
	{
		type: {
			type: String,
			required: true
		},
		commonField: String
	},
	{ discriminatorKey: 'type' }
);
const schema = new Schema({
	....
	slides: [slideSchema]
});


const slidesSchema = schema.path('slides');
slidesSchema.discriminator('typeA', new Schema({ a: String });
slidesSchema.discriminator('typeB', new Schema({b: string});

If I use something like :

MyModel.findOneAndUpdate(
		{
			'slides._id': id // this is a typeA slide
		},
		{
				a: 'test', // Will NOT be updated
 				commonField: 'newValue' // Will be updated
		{
			new: true,
			runValidators: true
		}
	);

#6087 seems to be related.

@vkarpov15 vkarpov15 modified the milestones: 5.8.0, 5.7.4 Sep 30, 2019
@vkarpov15 vkarpov15 added the needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue label Sep 30, 2019
@vkarpov15
Copy link
Collaborator

@SebT what you reported is expected behavior, because Mongoose has no way of knowing that slide._id corresponds to a slide of typeA. You should be able to do this though:

const mongoose = require('mongoose');
mongoose.set('debug', true);
mongoose.set('useFindAndModify', false);
const Schema = mongoose.Schema;

const slideSchema = new Schema(
        {
                type: {
                        type: String,
                        required: true
                },
                commonField: String
        },
        { discriminatorKey: 'type' }
);
const schema = new Schema({
        slides: [slideSchema]
});


const slidesSchema = schema.path('slides');
slidesSchema.discriminator('typeA', new Schema({ a: String }));
slidesSchema.discriminator('typeB', new Schema({b: String}));

const Slide = mongoose.model('Slide', schema);

const slidesSchema = schema.path('slides');
slidesSchema.discriminator('typeA', new Schema({ a: String }));
slidesSchema.discriminator('typeB', new Schema({b: String}));

const Slide = mongoose.model('Slide', schema);

run().catch(err => console.log(err));

async function run() {
  await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });
  const doc = await Slide.create({
    slides: [{ type: 'typeA', commonField: 'foo', a: 'bar' }]
  });

  await Slide.findOneAndUpdate(
                {
                        'slide':{ $elemMatch: { _id: doc.slides[0]._id, type: 'typeA' } } // <-- change here
                },
                {
                                'slides.$.a': 'test'
                                'slides.$.commonField': 'newValue'
                },
                {
                        new: true,
                        runValidators: true
                }
        );
}

However, that doesn't seem to work. Will fix that 👍

@vkarpov15 vkarpov15 added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue labels Oct 5, 2019
vkarpov15 added a commit that referenced this issue Oct 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

3 participants