Дискриминаторы
Функция model.discriminator()
Дискриминаторы — это механизм наследования схем. Они позволяют иметь несколько моделей с перекрывающимися схемами поверх одной и той же базовой коллекции MongoDB.
Предположим, вам нужно отслеживать различные типы событий в одной коллекции. Каждое событие будет иметь отметку времени, но события, представляющие нажатия на ссылки, должны иметь URL. Вы можете добиться этого, используя функцию model.discriminator(). Эта функция принимает 3 параметра: имя модели, схему дискриминатора и необязательный ключ (по умолчанию — имя модели). Она возвращает модель, схема которой является объединением базовой схемы и схемы дискриминатора.
const options = { discriminatorKey: 'kind' };
const eventSchema = new mongoose.Schema({ time: Date }, options);
const Event = mongoose.model('Event', eventSchema);
// ClickedLinkEvent is a special type of Event that has
// a URL.
const ClickedLinkEvent = Event.discriminator('ClickedLink',
new mongoose.Schema({ url: String }, options));
// When you create a generic event, it can't have a URL field...
const genericEvent = new Event({ time: Date.now(), url: 'google.com' });
assert.ok(!genericEvent.url);
// But a ClickedLinkEvent can
const clickedEvent = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
assert.ok(clickedEvent.url);
Дискриминаторы сохраняются в коллекцию модели "Событие"
Предположим, вы создали другой дискриминатор для отслеживания событий, где зарегистрировался новый пользователь. Эти экземпляры SignedUpEvent будут храниться в той же коллекции, что и общие события, и экземпляры ClickedLinkEvent.
const event1 = new Event({ time: Date.now() });
const event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
const event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
await Promise.all([event1.save(), event2.save(), event3.save()]);
const count = await Event.countDocuments();
assert.equal(count, 3);
Ключи дискриминатора
Способ, которым Mongoose различает различные модели дискриминаторов, — это «ключ дискриминатора», который по умолчанию __t. Mongoose добавляет строковый путь, называемый __t, к вашим схемам, который используется для отслеживания, экземпляром какого дискриминатора является данный документ.
const event1 = new Event({ time: Date.now() });
const event2 = new ClickedLinkEvent({ time: Date.now(), url: 'google.com' });
const event3 = new SignedUpEvent({ time: Date.now(), user: 'testuser' });
assert.ok(!event1.__t);
assert.equal(event2.__t, 'ClickedLink');
assert.equal(event3.__t, 'SignedUp');
Изменение ключа дискриминатора
По умолчанию Mongoose не позволяет изменять ключ дискриминатора. save() будет выводить ошибку, если вы попытаетесь изменить ключ дискриминатора. А findOneAndUpdate(), updateOne(), и т. д. будут игнорировать изменения ключа дискриминатора.
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"
await event.save();
event = await ClickedLinkEvent.findByIdAndUpdate(event._id, { __t: 'SignedUp' }, { new: true });
event.__t; // 'ClickedLink', update was a no-op
Чтобы изменить ключ дискриминатора документа, используйте findOneAndUpdate() или updateOne() с опцией overwriteDiscriminatorKey установленной следующим образом.
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
© 2010 LearnBoost
Licensed under the MIT License.
https://mongoosejs.com/docs/discriminators.html