【问题标题】:How can I add instance/static methods to Mongoose schema when using @nestjs/mongoose? (TypeScript Issues)使用 @nestjs/mongoose 时如何将实例/静态方法添加到 Mongoose 模式? (打字稿问题)
【发布时间】:2021-05-24 21:29:47
【问题描述】:

使用 vanilla Mongoose 时,直接转至 add methods to Mongoose schemas。 Mongoose 文档很好地解决了这个问题,并且可以找到几个示例。

但是当您在 Nest 应用程序的上下文中使用 Mongoose 时会怎样?我希望我的 Mongoose 模式更像“巢状”,所以我使用了 Mongoose 的 Nest 包装器 (@nestjs/mongoose)。但是,似乎缺少@nestjs/mongoose 的文档。我能找到的最接近任何文档的东西是 the guide for using MongoDB in a Nest app,它只包括 Mongoose 最基本的用例。

在我看来,Mongoose 在 Nest 世界中的使用方式与原版 Mongoose 的使用方式截然不同。也许这只是缺乏对 TypeScript 或 Nest 的熟悉,但我似乎无法真正理解这些差异,而且缺乏示例也无济于事。

我看到了一些关于如何在 StackOverflow 上实现这一点的答案,例如:

  • 解决方案 1 - example solution that adds a method to MySchema.methods
    • 此解决方案对我不起作用:TypeScript 仍然告诉我该类型不存在该属性。
  • 解决方案 2 - example solution using an interface that extends Model
    • 虽然使用我需要的方法添加新接口的这种解决方案确实使 TypeScript 认识到该方法对该类型有效,但我不确定如何实际实现它。我无法编写实现该接口的类,因为它需要实现 60 多个 Mongoose 模型方法,而我尝试编写的任何其他地方都不适合我的实现。

我该怎么做?

架构

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

export type CatDocument = Cat & Document;

@Schema()
export class Cat {
  @Prop()
  name: string;

  @Prop()
  age: number;

  @Prop()
  breed: string;
}

export const CatSchema = SchemaFactory.createForClass(Cat);

// ** Add methods here? **

服务

import { Model } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Cat, CatDocument } from './schemas/cat.schema';

@Injectable()
export class CatsService {
  constructor(@InjectModel(Cat.name) private catModel: Model<CatDocument>) {}

  async findAll(): Promise<Cat[]> {
    // Call our custom method here:
    return this.catModel.doSomething();
  }
}

【问题讨论】:

    标签: typescript mongoose nestjs


    【解决方案1】:

    这是我设法做到的:

    export type UserDocument = User & Document;
    
    @Schema()
    export class User extends Document {
      @Prop({ required: true, unique: true })
      email!: string;
      @Prop({ required: true })
      passwordHash!: string;
    
      toGraphql!: () => UserType;
    }
    
    export const UserSchema = SchemaFactory.createForClass(User);
    
    UserSchema.methods.toGraphql = function (this: User) {
      const user = new UserType();
    
      user.id = this._id;
      user.email = this.email;
    
      return user;
    };
    

    刚刚添加

    toGraphql!: () => 用户类型;

    上课

    【讨论】:

      【解决方案2】:

      实际上你是在模型上调用方法,你必须在创建的文档上调用方法,或者通过模型返回文档。

      模式上的方法。

      UserSchema.methods.comparePassword = async function(candidatePassword: string) {
        return await bcrypt.compare(candidatePassword, this.password);
      };
      

      包含已定义函数的接口。

      export interface User {
        comparePassword(candidatePassword: string): Promise<boolean>;
      }
      

      在我的情况下,我已经在使用具有用户和文档的 UserDocument。我在注入模型时添加它。

      constructor(
          @InjectModel(User.name) private readonly userModel: Model<UserDocument, UserFunction>
        ) {
        }
      
      @Injectable()
      export class AuthService {
        constructor(
          private readonly usersService: UsersService,
          private readonly jwtService: JwtService,
      ) { }
      
      async signIn({ email, password }: SignInDto): Promise<LoginResponse> {
      
      const user = await this.usersService.findByEmail(email); // Document found
      
      if (!user) { throw new UnauthorizedException('Invalid Username or Password'); }
      
      if (await user.comparePassword(password)) // <- Calling Schema method here {
      
        const tokenPayload: JwtPayload = { userId: user.id };
        const token = this.jwtService.sign(tokenPayload);
      
        return ({ token, userId: user.id, status: LoginStatus.success });
      } else {
        throw new UnauthorizedException('Invalid Username or Password');
      }
      

      我一直在调用 userModel 本身的方法,而不是在它的文档上调用它。感谢@Pantera answer 我发现了错误。

      【讨论】:

        猜你喜欢
        • 2022-01-24
        • 2013-06-06
        • 2015-06-22
        • 2020-09-29
        • 1970-01-01
        • 2021-03-18
        • 2013-11-12
        • 2020-10-17
        相关资源
        最近更新 更多