【发布时间】:2021-08-02 00:57:56
【问题描述】:
我已经开始使用 NestJS,从我的旧 express/mongoose 项目迁移并立即撞到栅栏,只是遵循 NestJS 文档中的 MongoDB/序列化章节。我准备了以下架构
/////// 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}
最后我发现只有手动实例化 User 类才能以某种方式完成它应该做的事情,所以我在 User 类中添加了构造函数
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"}
我错过了什么吗?不知怎的,这似乎有点压倒性......
更新:这是关于 NestJS mongoose 和序列化耦合的问题 - 为什么会这样
@UseInterceptors(ClassSerializerInterceptor)
@Get('first')
async first(): Promise<User> {
return await this.userModel.findOne().lean();
}
不起作用,这个
@UseInterceptors(ClassSerializerInterceptor)
@Get('first')
async first(): Promise<User> {
return new User(await this.userModel.findOne().lean());
}
有效(这也意味着对于每个需要创建实体的结果可枚举映射)
【问题讨论】:
-
我有一个问题要问你,你想隐藏每次选择还是创建?
-
这要么是关于 Nestjs 猫鼬和序列化耦合 - 为什么这个
@UseInterceptors(ClassSerializerInterceptor) ... return await this.userModel.findOne().lean()不起作用而这个@UseInterceptors(ClassSerializerInterceptor) ... return new User(await this.userModel.findOne().lean())起作用 -
最后有没有找到好的解决方案?我也面临同样的情况
-
最后我使用了构造函数和返回多个项目的方法,我最终使用了 async findAll(): Promise
{ return (await this.userModel.find().lean(). exec()).map(user => new User(user)) } 不太满意
标签: javascript nestjs nestjs-mongoose