NestJS/Mongoose:序列化不排除纯输出中的属性

问题描述

我已经开始使用 nestjs,从我的旧 express/mongoose 项目迁移,并立即陷入围栏,只是按照 nestjs 文档中的 mongodb/serializations 章节进行操作。我准备了以下架构

^D

在 app.module 中注册

/////// schema
import { Prop,Schema,SchemaFactory } from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
import { Exclude,Expose } from 'class-transformer';

export type UserDocument = User & mongoose.Document;

@Schema()
export class User {
    @Prop()
    @Exclude()
    _id: String

    @Expose()
    get id(): String { return this._id ? `${this._id}` : undefined }

    @Prop()
    name: string

    @Prop({ unique: true })
    login: string

    @Exclude()
    @Prop()
    password: string        
}

export const UserSchema = SchemaFactory.createForClass(User);

并尝试了以下调用,期望结果中没有显示密码属性

MongooseModule.forRoot('mongodb://localhost/old_project'),MongooseModule.forFeature([ { name: User.name,schema: UserSchema } ]),

最后我发现只有手动实例化 User 类才能以某种方式完成它应该做的事情,所以我在 User 类中添加了构造函数

/////// controller
  @UseInterceptors(ClassSerializerInterceptor)
  @Get('default')
  async default(): Promise<User> {
    let u = new User();
    u.name = 'Kos';
    u.password = "secret";
    u.login = 'k@o.s'

    return u;
  }
  
  // returns
  // {"name":"Kos","login":"k@o.s"}

  @Get('first_raw')
  async firstRaw(): Promise<User> {
    return this.usermodel.findOne()
  }
  
  @Get('first_lean')
  async firstLean(): Promise<User> {
    return this.usermodel.findOne().lean()
  }
  
  //both return
  // {"_id":"5f8731a36fc003421db08921","name":"Kos","login":"kos","password":"secret","__v":0}

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first_raw_stripped')
  async firstRawStripped(): Promise<User> {
    return this.usermodel.findOne()
  }
  
  //returns
  // {"$__":{"strictMode":true,"selected":{},"getters":{},"_id":"5f8731a36fc003421db08921","waspopulated":false,"activePaths":{"paths":{"_id":"init","name":"init","login":"init","password":"init","__v":"init"},"states":{"ignore":{},"default":{},"init":{"_id":true,"name":true,"login":true,"password":true,"__v":true},"modify":{},"require":{}},"stateNames":["require","modify","init","default","ignore"]},"pathsToScopes":{},"cachedrequired":{},"$setCalled":[],"emitter":{"_events":{},"_eventsCount":0,"_maxListeners":0},"$options":{"skipId":true,"isNew":false,"willInit":true,"defaults":true}},"$locals":{},"$op":null,"_doc":{"_id":"5f8731a36fc003421db08921","__v":0},"$init":true}

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first_lean_stripped')
  async firstLeanStripped(): Promise<User> {
    return this.usermodel.findOne().lean()
  }
  
  //returns
  // {"_id":"5f8731a36fc003421db08921","__v":0}

然后它最终返回了预期的结果 - 结果中没有密码道具

constructor(partial?: Partial<User>) {
    if (partial)
        Object.assign(this,partial);
}

我错过了什么吗?不知怎的,这似乎有点压倒性...

更新:这要么是关于 nestjs mongoose 和序列化耦合的问题——为什么会这样

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first')
  async first(): Promise<User> {
    return new User(await this.usermodel.findOne().lean());
  }
  
  //finally returns what's expected
  // {"name":"Kos","__v":0,"id":"5f8731a36fc003421db08921"}

不起作用,这个

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first')
  async first(): Promise<User> {
    return await this.usermodel.findOne().lean();
  }

有效(这也意味着对于每个结果都需要创建实体的可枚举映射)

解决方法

我想我有办法

@Schema()
export class User {
  @Prop({select: false})
  password: string;
  @Prop()
  username: string;
}

当你对装饰器执行这个 prop 时,mongo 内部属性的值在 finds 中被忽略。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...