How to define mongoose method in schema class with using nestjs/mongoose?
Asked Answered
S

4

11

I want to implement method in schema class like below.

import { SchemaFactory, Schema, Prop } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import bcrypt from 'bcrypt';

@Schema()
export class Auth extends Document {
  @Prop({ required: true, unique: true })
  username: string;

  @Prop({ required: true })
  password: string;

  @Prop({
    methods: Function,
  })
  async validatePassword(password: string): Promise<boolean> {
    return bcrypt.compareAsync(password, this.password);
  }
}
export const AuthSchema = SchemaFactory.createForClass(Auth);

this schema return undefined when log the method . How can I write method in class schema with nestjs/mongoose package?

Sitar answered 10/6, 2020 at 7:43 Comment(4)
That would be instance methods. Are you looking for static methods?Grassy
No i'm looking for instance methods. I can't define it inside classSitar
The Schema will definitely return undefined for validatePassword since it is an instance method which it is on the model, not the schema.Grassy
Ya,you say true but the point is how to write method on schemaSitar
O
30

You can use below approach to achieve this.

@Schema()
export class Auth extends Document {
    ...
    
    validatePassword: Function;
}

export const AuthSchema = SchemaFactory.createForClass(Auth);

AuthSchema.methods.validatePassword = async function (password: string): Promise<boolean> {
    return bcrypt.compareAsync(password, this.password);
};
Oquendo answered 15/10, 2020 at 18:55 Comment(4)
Hi, new to typed mongo in nestjs. Why cant we define these instance methods in the @Schema decorator with methods option. I tired this but it doesnt seem to work! Thanks for your solution, it works! Just wondering why its provided in the decorator and if you are aware of how to use it @Suroor AhmmadWherewith
With the @Schema() decorator, you can only specify the schema and not define the method inside it.Oquendo
Ok thanks, just wondering why we can define an instance/methods object with functions in it in @Schema() decorator in @nestjs/mongoose. But yes it does not work I am wondering what is the use of this option that we can pass to the @Schema decorator.Wherewith
@SuroorAhmmad thank you for this. When I try a similar approach, I cannot reference this within the method: it complains that it is possibly 'undefined'. Any hints as to why that is? Thanks in advance!Tadio
T
3

Try AuthSchema.loadClass(Auth) (Advanced Schemas: Creating from ES6 Classes Using loadClass()):

import { SchemaFactory, Schema, Prop } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import bcrypt from 'bcrypt';

@Schema()
export class Auth extends Document {
  @Prop({ required: true, unique: true })
  username: string;

  @Prop({ required: true })
  password: string;

  async validatePassword(password: string): Promise<boolean> {
    return bcrypt.compareAsync(password, this.password);
  }
}
export const AuthSchema = SchemaFactory.createForClass(Auth);

// This function lets you pull in methods, statics, and virtuals from an ES6 class.
AuthSchema.loadClass(Auth);

Make sure all the properties you use in your method are annotated with the @Prop() decorator, otherwise, they will be undefined.

Tate answered 2/11, 2023 at 15:54 Comment(0)
Z
0

Use this function instead of SchemaFactory.createForClass(Auth):

export function createSchema(document: any) {
  const schema = SchemaFactory.createForClass(document);

  const instance = Object.create(document.prototype);

  for (const objName of Object.getOwnPropertyNames(document.prototype)) {
    if (
      objName != 'constructor' &&
      typeof document.prototype[objName] == 'function'
    ) {
      schema.methods[objName] = instance[objName];
    }
  }

  return schema;
}
Zenger answered 30/12, 2021 at 14:53 Comment(0)
S
0

When using TypeScript with Mongoose, directly defining the method on the schema object without loadClass may not work as expected due to the intricacies of TypeScript's type system.

In Mongoose, the loadClass method is specifically designed to handle the association of the class methods with the schema. Without it, TypeScript might not recognize the custom methods on instances of the model.

after creating schema, load class to make it accessible outside AuthSchema.loadClass(Auth);

Shows answered 31/1 at 7:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.