Giter VIP home page Giter VIP logo

Comments (34)

Crackz avatar Crackz commented on May 5, 2024 6

I think this is the most elegant solution :

Create your parent model as usual

	imports: [
		MongooseModule.forFeature([{ name: ANIMAL_MODEL_NAME, schema: AnimalSchema }]),
	],

To create a child model


	providers: [
		{
		provide: getModelToken(CAT_MODEL_NAME),
		useFactory: (animalModel) =>
			animalModel.discriminator(CAT_MODEL_NAME, CatSchema),
		inject: [getModelToken(ANIMAL_MODEL_NAME)]
	        }
	],

@kamilmysliwiec Thank you so much !! great architecture !

from mongoose.

juandav avatar juandav commented on May 5, 2024 3

@kamilmysliwiec how discriminators are used with this library? it's possible?

from mongoose.

ssi-hu-tasi-norbert avatar ssi-hu-tasi-norbert commented on May 5, 2024 1

Hey,

Finally I've could managed to solve the issue. The discrimination rules must be added in the service constructor after the model injected because in the schema file it didn't worked. You can close this issue since has a workaround.

Thanks for your great library!

from mongoose.

kamilmysliwiec avatar kamilmysliwiec commented on May 5, 2024 1

It would be great if you can share your solution with other people so they could use it as a reference :)

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024 1

I made it work without need for using same provider in multiple modules
But thank you
It will be maybe useful sometimes @Crackz

from mongoose.

mkbrdigital avatar mkbrdigital commented on May 5, 2024 1

I made it work without need for using same provider in multiple modules
But thank you
It will be maybe useful sometimes @Crackz

@NenadJovicic

How? Im facing same issue...

from mongoose.

vtrphan avatar vtrphan commented on May 5, 2024 1

@Crackz thanks for the example. I wanted to ask how i can do it using nestjs/mongoose style, i.e using class with decorator etc.. Can you please show me an example on how to do that using class with decorator style? thanks

from mongoose.

Pong420 avatar Pong420 commented on May 5, 2024 1

@WarKaa Sorry, it was deleted.
you could take a looks on
https://github.com/nestjs/mongoose/blob/master/tests/e2e/discriminator.spec.ts

or my other repo which using discriminators
https://github.com/taisiusyut/taisiusyut/tree/master/packages/server/src/modules/user/schemas

from mongoose.

Crackz avatar Crackz commented on May 5, 2024 1

I'd recommend using the nest mongoose way that you mentioned

you can find my example here It's for the ones who aren't comfortable with nest mongoose abstracting their schemas

from mongoose.

ssi-hu-tasi-norbert avatar ssi-hu-tasi-norbert commented on May 5, 2024

For me the discriminators array is undefined in the service.

from mongoose.

ssi-hu-tasi-norbert avatar ssi-hu-tasi-norbert commented on May 5, 2024

I have a workaround. In the service constructor I could add the discriminators and it works, but not with save method during creation, only the this.model.create(... save works for update only. However would be nice to handle it in module after providers are imported.

from mongoose.

kamilmysliwiec avatar kamilmysliwiec commented on May 5, 2024

Honestly, I don't understand the problem. Discriminators can be used in the same way as in the normal, pure mongoose app.

from mongoose.

matze1234 avatar matze1234 commented on May 5, 2024

@ssi-hu-tasi-norbert can you share an example please?

from mongoose.

ssi-hu-tasi-norbert avatar ssi-hu-tasi-norbert commented on May 5, 2024

https://github.com/norbert-tasi/nestjs-mongoose

pls look for question.schema for discriminators. question.service does the trick.
I hope it helps you!

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

@Crackz and how do you use it in some service?
how do you inject that child model?
with @InjectModel(CAT_MODEL_NAME) catModel: Model<CatSchema> ??
Because I tried it like this, and it didn't work
So, can you explain me how do you do some query on that specific child model?

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

@Crackz and also, what if you need same child model in 2 different modules?
i tried to define them in 2 different modules, and was not able to do it, error was that specific model can't be defined twice

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

@ssi-hu-tasi-norbert but looking at that example, how can you know does it return you a model for email or range or datebox?
for example i want to query only for questions that are emails, and i want it to return me some Document that is generated for example from EmailSchema?
lets say i have created some type-safe document out of this schema and want to type output of some query to this document

from mongoose.

ssi-hu-tasi-norbert avatar ssi-hu-tasi-norbert commented on May 5, 2024

You set the discriminatorKey to whatever you want. In my example: discriminatorKey: 'kind'
The kind is a field/attribute just like others. You can query it.

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

I am sorry @Crackz , I made a mistake
this solution is working really nice.
I made a mistake because i use {} around this discriminator call, so i missed return inside of it
only problem with this is, if you need same model in 2 different modules, because you can't initialize it twice

but thanks for help

from mongoose.

Crackz avatar Crackz commented on May 5, 2024

Hi, @NenadJovicic
i have not tested your given case because i use repository pattern. anyway i'd suggest you to export your child model which is one of the providers ! so any other module would import it . you will be able to @InjectModel(CHILD_MODEL_NAME) into it !

from mongoose.

ksugiarto avatar ksugiarto commented on May 5, 2024

I think this is the most elegant solution :

Create your parent model as usual

	imports: [
		MongooseModule.forFeature([{ name: ANIMAL_MODEL_NAME, schema: AnimalSchema }]),
	],

To create a child model


	providers: [
		{
		provide: getModelToken(CAT_MODEL_NAME),
		useFactory: (animalModel) =>
			animalModel.discriminator(CAT_MODEL_NAME, CatSchema),
		inject: [getModelToken(ANIMAL_MODEL_NAME)]
	        }
	],

Hi @Crackz, I'm sorry, I am a little bit lost on how to initialize or inject the model of animalModel in the provider here:

  useFactory: (animalModel) =>

Could you kindly explain how to get it? 🙏

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

To use it in some service that is in same module, it is easy
Because you just do standard NestJS

constructor(@InjectModel(CAT_MODEL_NAME) private catModel: Model<CatDocument>) 

I only don't know how to use this same model in different module
@ksugiarto

from mongoose.

NenadJovicic avatar NenadJovicic commented on May 5, 2024

@Crackz I also separate logic by modules, but had some case where I had to use same model in 2 different modules, and this solution was not working

from mongoose.

Crackz avatar Crackz commented on May 5, 2024

@NenadJovicic i made a fully working example. i hope you find it useful

https://github.com/Crackz/nest-mongoose-discriminator-test

from mongoose.

sae13 avatar sae13 commented on May 5, 2024

Hey,

Finally I've could managed to solve the issue. The discrimination rules must be added in the service constructor after the model injected because in the schema file it didn't worked. You can close this issue since has a workaround.

Thanks for your great library!

can you send a example please

from mongoose.

vtrphan avatar vtrphan commented on May 5, 2024

hi, i need to both define the discriminator AND use hooks (pre, post). So if i define the discriminator in a provider like the example of @Crackz , where can i then define the hooks (in other examples i see hooks are defined in the MoongooseModule.forFeatureAsync factory). Please advise.

from mongoose.

Crackz avatar Crackz commented on May 5, 2024

@vtrphan
If you take a look at this example
you'd have a traditional mongoose schema so you can do it like this :

import { Schema } from 'mongoose';

const CatSchema: Schema = new Schema(
	{
		bad: { 
			type: Boolean,
			default: false
		}
	},
	{ discriminatorKey: 'type' }
);

CatSchema.pre('save', function (next) {
	console.log('meow!!!!!!!!');
});


export { CatSchema };

from mongoose.

vtrphan avatar vtrphan commented on May 5, 2024

@Crackz any idea how i can use mongoose hooks and discriminator with nestjs/mongoose style (class with decorators) instead of traditional mongoose schema? Thanks

from mongoose.

Crackz avatar Crackz commented on May 5, 2024

@vtrphan sorry, I know nothing about nestjs/mongoose decorators because i think it's unnecessary level of abstraction.
i'd recommend you creating a new issue asking @kamilmysliwiec

from mongoose.

johnfrades avatar johnfrades commented on May 5, 2024

Hi @Crackz i tried your solution but im getting an error
Cannot overwrite Processor model once compiled. at Function.Model.discriminator (/home/john/Documents/Projects/pchubbuilder/node_modules/mongoose/lib/model.js:1125:11)

i just provided the provider and i got this error.
This is my code

@Module({
  imports: [
    MongooseModule.forFeature([
      PCBUILD_FEATURE,
      PART_FEATURE,
      NOTIFICATION_POOL_FEATURE,
      USER_FEATURE,
      PROCESSOR_FEATURE,
    ]),
  ],
  controllers: [PcBuildController],
  providers: [
    PcBuildService,
    {
      provide: getModelToken('Processor'),
      useFactory: partModel =>
        partModel.discriminator('Processor', ProcessorSchema),
      inject: [getModelToken(PART_FEATURE.name)],
    },
  ],
})
export class PcBuildModule {}

Do you know what is this error? Thanks!

from mongoose.

Crackz avatar Crackz commented on May 5, 2024

@johnfrades Sorry For The Late Reply

i'd move PART_FEATURE to its own module and just import it into the child module
check animal module in the example

from mongoose.

Pong420 avatar Pong420 commented on May 5, 2024

@vtrphan Here is an example for single-nested-discriminators.

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Circle, CircleSchema } from './circle.schema';
import { Square, SquareSchema } from './square.schema';

@Schema({ discriminatorKey: 'kind' })
export class Shape {
  @Prop({ type: String, required: true })
  kind: string;
}

export const ShapeSchema = SchemaFactory.createForClass(Shape);

@Schema()
export class ShapeTest {
  @Prop({ type: ShapeSchema, required: true })
  shape: Shape;
}

export const ShapeTestSchema = SchemaFactory.createForClass(ShapeTest);

ShapeTestSchema.path('shape').discriminator(Circle.name, CircleSchema);
ShapeTestSchema.path('shape').discriminator(Square.name, SquareSchema);

You may also need the type definition, @types/mongoose is not supported yet ( related issue ). Remember to set skipLibCheck to false in tsconfig.json

declare module 'mongoose' {
  class SchemaType {
    discriminator<U extends Document>(name: string, schema: Schema): Model<U>;
  }
}

from mongoose.

WarKaa avatar WarKaa commented on May 5, 2024

Hey @Pong420, is your repo still available ?

from mongoose.

kasir-barati avatar kasir-barati commented on May 5, 2024

I think this is the most elegant solution :

Create your parent model as usual

	imports: [
		MongooseModule.forFeature([{ name: ANIMAL_MODEL_NAME, schema: AnimalSchema }]),
	],

To create a child model


	providers: [
		{
		provide: getModelToken(CAT_MODEL_NAME),
		useFactory: (animalModel) =>
			animalModel.discriminator(CAT_MODEL_NAME, CatSchema),
		inject: [getModelToken(ANIMAL_MODEL_NAME)]
	        }
	],

@kamilmysliwiec Thank you so much !! great architecture !

please share more info. if it is possible please create a repo for your solution

and as a extra information for others: in nestjs DOC there is a very simple and good way to deal with discriminators.

from mongoose.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.