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

NestJS/Mongoose:序列化不排除普通输出中的属性,nestjs,nestjs-mongoose,Nestjs,Nestjs Mongoose,我开始玩nestjs,从我以前的express/mongoose项目迁移过来,紧接着nestjs文档中的mongodb/serializations章节,我立即撞上了围栏。我已经准备好了下面的模式 /////// schema import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import * as mongoose from 'mongoose'; import { Exclude, Expose } from 'c

我开始玩nestjs,从我以前的express/mongoose项目迁移过来,紧接着nestjs文档中的mongodb/serializations章节,我立即撞上了围栏。我已经准备好了下面的模式

/////// 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);
已在app.module中注册

MongooseModule.forRoot('mongodb://localhost/old_project'), 
MongooseModule.forFeature([ { name: User.name, schema: UserSchema } ]),
并尝试了以下调用,希望结果中没有显示密码属性

/////// 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}},"isNew":false,"$locals":{},"$op":null,"_doc":{"_id":"5f8731a36fc003421db08921","name":"Kos","login":"kos","password":"secret","__v":0},"$init":true}

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first_lean_stripped')
  async firstLeanStripped(): Promise<User> {
    return this.userModel.findOne().lean()
  }
  
  //returns
  // {"_id":"5f8731a36fc003421db08921","name":"Kos","login":"kos","password":"secret","__v":0}
///controller
@UseInterceptors(ClassSerializerInterceptor)
@获取('默认')
异步默认值():承诺{
设u=新用户();
u、 名称='Kos';
u、 password=“secret”;
u、 登录k@o.s'
返回u;
}
//返回
//{“name”:“Kos”,“login”:k@o.s"}
@获取('first_raw')
异步firstRaw():承诺{
返回这个.userModel.findOne()
}
@获取(“第一个倾斜”)
异步firstLean():承诺{
返回此.userModel.findOne().lean()
}
//两者都返回
//{“_id”:“5f8731a36fc003421db08921”,“名称”:“Kos”,“登录”:“Kos”,“密码”:“secret”,“_v”:0}
@UseInterceptors(ClassSerializerInterceptor)
@获取(‘第一次未加工’)
异步firstRawStripped():承诺{
返回这个.userModel.findOne()
}
//返回
//{${uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,“stateNames”:[“require”,“modify”,“init”,“default”,“ignore”]},“pathsToScopes”:{},“cachedRequired”:“{}”,“setCalled”:[]”,“emitter”:“{u events”:{}”,“eventscont”:“0”,“maxListeners”:0},“$options”:{“skipId”:true,“isNew”:false,“defaults”:true},“true”;“true},“isNew”;“isNew”;“false“$locals”:“{}”,“isNew”;“{”;“op”:null“{doc id”:“{f85731afc03421db021”,“kosfc8921”:“login”:“:”kos“,”密码“:”secret“,”__v“:0},“$init”:true}”
@UseInterceptors(ClassSerializerInterceptor)
@获取(‘第一次精简’)
异步firstLeanStripped():承诺{
返回此.userModel.findOne().lean()
}
//返回
//{“_id”:“5f8731a36fc003421db08921”,“名称”:“Kos”,“登录”:“Kos”,“密码”:“secret”,“_v”:0}
最后,我发现只有用户类的手动实例化才能完成它应该做的事情,所以我向用户类添加了构造函数

constructor(partial?: Partial<User>) {
    if (partial)
        Object.assign(this, partial);
}
构造函数(部分?:部分){
如果(部分)
对象。分配(此,部分);
}
然后它最终返回了预期的结果-结果中没有密码道具

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first')
  async first(): Promise<User> {
    return new User(await this.userModel.findOne().lean());
  }
  
  //finally returns what's expected
  // {"name":"Kos","login":"kos","__v":0,"id":"5f8731a36fc003421db08921"}
@UseInterceptors(ClassSerializerInterceptor)
@获取('第一')
async first():承诺{
返回新用户(等待this.userModel.findOne().lean());
}
//最终返回预期结果
//{“name”:“Kos”,“login”:“Kos”,“__v”:0,“id”:“5f8731a36fc003421db08921”}
我错过什么了吗?不知何故,这似乎有点让人难以承受

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

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first')
  async first(): Promise<User> {
    return await this.userModel.findOne().lean();
  }
@UseInterceptors(ClassSerializerInterceptor)
@获取('第一')
async first():承诺{
return wait this.userModel.findOne().lean();
}
不起作用,这个

  @UseInterceptors(ClassSerializerInterceptor)
  @Get('first')
  async first(): Promise<User> {
    return new User(await this.userModel.findOne().lean());
  }
@UseInterceptors(ClassSerializerInterceptor)
@获取('第一')
async first():承诺{
返回新用户(等待this.userModel.findOne().lean());
}

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

我想我已经找到了解决方案

@Schema()
导出类用户{
@属性({select:false})
密码:字符串;
@支柱(
用户名:字符串;
}

当您对装饰器执行此操作时,mongo内部属性的值在查找中被忽略。

我有一个问题要问您,您是否希望在每次选择或创建时都隐藏?这是关于nestjs mongoose和序列化耦合的问题-为什么这
@UseInterceptors(ClassSerializerInterceptor)。。。return wait this.userModel.findOne().lean()
不起作用,此
@UseInterceptors(ClassSerializerInterceptor)。。。返回新用户(等待此.userModel.findOne().lean())
worksNo,我只想从UI部分隐藏此字段的值,这样我就可以执行console.log(User.password)或任何等式检查,但将用户实体返回到前端,而不需要有价值的道具