[Feature Request] egg-mongoose support mongoose discriminator

a6b3iqyw  于 5个月前  发布在  Go
关注(0)|答案(1)|浏览(61)

Background

Discriminators are a schema inheritance mechanism. They enable you to have multiple models with overlapping schemas on top of the same underlying MongoDB collection.

Current egg-mongoose use the function loadModelToApp to load Models to app.model. However, during loading, I can't get the base Model at another Model.

for instance, I have app/model/Event.js as a base model, and app/model/ClickedLinkEvent.js as another discriminator.

app/model/Event.js

var eventSchema = new mongoose.Schema({time: Date}, options);
return mongoose.model('Event', eventSchema);

app/model/ClickedLinkEvent.js

// I can't get the Event Model here
const { Event } = app.model;
var ClickedLinkEvent = Event.discriminator('ClickedLink',
  new mongoose.Schema({url: String}, options));

Proposal

find a way to support mongoose discriminator

oogrdqng

oogrdqng1#

My workaround for this for now is to put the discriminators in the same file as the base model.

// app/model/event.ts
import { Application } from 'egg';

export default (app: Application) => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;

  const options = { discriminatorKey: 'kind' };

  const eventSchema = new Schema({ time: Date }, options);
  const Event = mongoose.model('Event', eventSchema);

  Event.discriminator(
    'ClickedLink',
    new mongoose.Schema({ url: String }, options)
  );

  return Event;
};

If you want to have the discriminators in separate files, you can put the register discriminator handle in another file, import it and pass Event model to it.
Example

// app/model/Event.ts
import { Application } from 'egg';
import { registerClickedLink } from './ClickedEvent';

export default (app: Application) => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;

  const options = { discriminatorKey: 'kind' };

  const eventSchema = new Schema({ time: Date }, options);
  const Event = mongoose.model('Event', eventSchema);

  registerClickedLink(app, Event);

  return Event;
};

// app/model/ClickedEvent.ts
import { Application } from 'egg';
import { Model, Document } from 'mongoose';

export const registerClickedLink = (
  app: Application,
  baseModel: Model<Document>,
) => {
  const options = { discriminatorKey: 'kind' };
  baseModel.discriminator(
    'ClickedLink',
    new app.mongoose.Schema({ url: String }, options),
  );
};

Then I can create it like this or fetch the discriminator from this.app.model.Event.discriminators

const clickedEvent = new this.app.model.Event({
  kind: 'ClickedLink',
  time: Date.now(),
  url: 'google.com',
});

await clickedEvent.save();

If anyone have any better alternatives, please do share.

相关问题