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
Add discriminator key to findOneAndUpdate #6087
Comments
i think this is a reasonable feature request, thoughts @vkarpov ? here's an example: const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const Schema = mongoose.Schema;
const GITHUB_ISSUE = `gh-6087`;
/* ============ */
run().catch(error => console.error(error.stack));
async function run() {
await mongoose.connect(`mongodb://localhost:27017/${GITHUB_ISSUE}`);
const messageSchema = new Schema({ text: String });
const Message = mongoose.model('Message', messageSchema);
const attachmentMessageSchema = new Schema({
type: { type: String, default: 'ATTACHMENT' },
attachment: String,
});
const AttachmentMessage = Message.discriminator(
'AttachmentMessage',
attachmentMessageSchema,
);
const doc = await AttachmentMessage.create({ attachment: 'lol' });
const update = await Message.findOneAndUpdate({ _id: doc._id, __t: 'AttachmentMessage' }, { attachment: 'test' }, { new: true });
console.log(update);
} In that last log, if this feature were implemented, it would have succsesfully updated |
@varunjayaraman Would it be feasible to remove the need to pass
From an API design standpoint, this feature above would simplify a generic update endpoint from this:
To this:
|
yeah i was posting that more as a proof of concept of how it would work under the hood :) |
@JonathanZWhite, @rawalyogendra asked about this on the gitter.im channel for mongoose as well. I wrote a wrapper around the mongoose.model that works pretty well so far, at least in the interim while new features are developed in mongoose 5. here is a gist . I'm pretty new to javascript and mongoose, so I'd like to know if this is a really bad idea, just ok, or if it's useful. |
Just want to flag that this would be super helpful for our app us as well. Would be awesome if this does get prioritized soon. Thanks for all the great work on Mongoose! |
In the same regard, I noticed that this works: Message.create({
...
__t: 'AttachmentMessage'
}) It will then do validation against correct discriminator schema. But this does not work: Message.insertMany([{
...
__t: 'AttachmentMessage'
}]) It will just drop all properties that are specific to the attachmentMessageSchema. @vkarpov15 Does that belong to the same feature request as this issue, or should a new issue be created for that? |
@thernstig new issue. I'll open one now. |
Since The current approach of updating from the discriminator model has an issue as highlighted on #7843 when using findOneAndUpdate or findByIdAndUpdate. Since they "attach the discriminator key to queries" it will not match an existing doc with a different discriminatorKey value.
ie. you can only change the discriminatorKey value from the base model and therefore can not also include additional attributes defined only in the changed (destination) discriminator model. |
I can understand the logic behind automatically attaching the discriminator key to certain queries for convenience but I think it needs to be optional.
|
@nhitchins the problem in this issue is that if you use |
I've been having the same issue as @nhitchins. If the update changes the type of the document via a different, but valid, discriminatorKey, using the new discriminator model for the
edit: current work-around is to update the document twice.
Then, update on the new model with the original update:
Functional, but not exactly optimal |
For 5.10 we'll add an 'use strict';
const mongoose = require('mongoose');
mongoose.set('debug', true);
mongoose.set('useFindAndModify', false);
const { Schema } = mongoose;
run().catch(err => console.log(err));
async function run() {
await mongoose.connect('mongodb://localhost:27017/test', {
useNewUrlParser: true,
useUnifiedTopology: true
});
await mongoose.connection.dropDatabase();
const baseSchema = new Schema({}, { discriminatorKey: 'type' });
const baseModel = mongoose.model('thing', baseSchema);
const aSchema = new Schema(
{
aThing: { type: Number },
},
{ _id: false, id: false },
);
const aModel = baseModel.discriminator('A', aSchema);
const bSchema = new Schema(
{
bThing: { type: String },
},
{ _id: false, id: false },
);
const bModel = baseModel.discriminator('B', bSchema);
// Model is created as a type A
const doc = await baseModel.create({ type: 'A', aThing: 1 });
await bModel.findByIdAndUpdate(
doc._id,
{ type: 'A', bThing: 'one', aThing: '2' },
{ runValidators: true, overwriteDiscriminatorKey: true },
);
} |
Hi @vkarpov15 , Thank you for your work :). I checked your example, however, the type has not been modified. It's still 'A'. Best, |
@himito you're right, the example was incorrect. Below is a corrected example: 'use strict';
const mongoose = require('mongoose');
run().catch(err => console.log(err));
async function run() {
await mongoose.connect('mongodb://localhost:27017/test');
await mongoose.connection.dropDatabase();
const baseSchema = new mongoose.Schema({}, { discriminatorKey: 'type' });
const baseModel = mongoose.model('thing', baseSchema);
const aSchema = new mongoose.Schema({ aThing: Number }, { _id: false, id: false });
const aModel = baseModel.discriminator('A', aSchema);
const bSchema = new mongoose.Schema({ bThing: String }, { _id: false, id: false });
const bModel = baseModel.discriminator('B', bSchema);
// Model is created as a type A
const doc = await baseModel.create({ type: 'A', aThing: 1 });
// Update the type to 'B'
const updated = await aModel.findByIdAndUpdate(
doc._id,
{ type: 'B', bThing: 'one', aThing: '2' },
{ runValidators: true, overwriteDiscriminatorKey: true, new: true },
);
console.log(updated.type); // 'B'
} |
Thank you @vkarpov15 ! |
docs(discriminators): add section about changing discriminator key
@vkarpov15 the code example you provided doesn't work for custom discriminator model names. |
Do you want to request a feature or report a bug?
Feature
What is the current behavior?
If I have the following discriminators:
In order to update an instance of
AttachmentMessage
I would have to writeAttachmentMessage.findOneAndUpdate
. If I writeMessage.findOneAndupdate
no changes will occur.I think this is because the discriminator key is only added to
find()
,count()
, andaggregate
. As the docs state:However, there are cases where the server might not be aware of the discriminator type of the model I want to update. For example, the client might pass a generic message payload:
Ideally, it would be nice to be able to pass that payload to the following function:
Could we automatically add the discriminator key to functions like
findOneAndUpdate
to address these cases? I saw a PR in Mongoose Schema extended that seems to model the desired behavior: https://github.com/briankircho/mongoose-schema-extend/pull/53/filesPlease mention your node.js, mongoose and MongoDB version.
Node: 8.4.0
Mongo: 3.0.7
Mongoose: 4.4.6
The text was updated successfully, but these errors were encountered: