diff --git a/docs/discriminators.md b/docs/discriminators.md index 72fdda371c1..e97e4ad1373 100644 --- a/docs/discriminators.md +++ b/docs/discriminators.md @@ -31,12 +31,25 @@ instances. ### Discriminator keys -The way mongoose tells the difference between the different -discriminator models is by the 'discriminator key', which is -`__t` by default. Mongoose adds a String path called `__t` -to your schemas that it uses to track which discriminator -this document is an instance of. +The way Mongoose tells the difference between the different discriminator models is by the 'discriminator key', which is `__t` by default. +Mongoose adds a String path called `__t` to your schemas that it uses to track which discriminator this document is an instance of. ```javascript [require:Discriminator keys] ``` + +### Updating the discriminator key + +By default, Mongoose doesn't let you update the discriminator key. +`save()` will throw an error if you attempt to update the discriminator key. +And `findOneAndUpdate()`, `updateOne()`, etc. will strip out discriminator key updates. + +```javascript +[require:Update discriminator key] +``` + +To update a document's discriminator key, use `findOneAndUpdate()` or `updateOne()` with the `overwriteDiscriminatorKey` option set as follows. + +```javascript +[require:use overwriteDiscriminatorKey to change discriminator key] +``` \ No newline at end of file diff --git a/test/docs/discriminators.test.js b/test/docs/discriminators.test.js index b13abb16fc9..883a635097f 100644 --- a/test/docs/discriminators.test.js +++ b/test/docs/discriminators.test.js @@ -100,6 +100,42 @@ describe('discriminator docs', function() { assert.equal(event3.__t, 'SignedUp'); }); + it('Update discriminator key', async function() { + let event = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' }); + await event.save(); + + event.__t = 'SignedUp'; + // ValidationError: ClickedLink validation failed: __t: Cast to String failed for value "SignedUp" (type string) at path "__t" + // acquit:ignore:start + await assert.rejects(async () => { + // acquit:ignore:end + await event.save(); + // acquit:ignore:start + }, /__t: Cast to String failed/); + // acquit:ignore:end + + event = await ClickedLinkEvent.findByIdAndUpdate(event._id, { __t: 'SignedUp' }, { new: true }); + event.__t; // 'ClickedLink', update was a no-op + // acquit:ignore:start + assert.equal(event.__t, 'ClickedLink'); + // acquit:ignore:end + }); + + it('use overwriteDiscriminatorKey to change discriminator key', async function() { + let event = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' }); + await event.save(); + + event = await ClickedLinkEvent.findByIdAndUpdate( + event._id, + { __t: 'SignedUp' }, + { overwriteDiscriminatorKey: true, new: true } + ); + event.__t; // 'SignedUp', updated discriminator key + // acquit:ignore:start + assert.equal(event.__t, 'SignedUp'); + // acquit:ignore:end + }); + /** * Discriminator models are special; they attach the discriminator key * to queries. In other words, `find()`, `count()`, `aggregate()`, etc.