如何让 class-transform 正确转换 mongoDb class 的 _id?
How to have class-transform converting properly the _id of a mongoDb class?
我有以下 mongoDb class:
@Schema()
export class Poker {
@Transform(({ value }) => value.toString())
_id: ObjectId;
@Prop()
title: string;
@Prop({ type: mongoose.Schema.Types.ObjectId, ref: User.name })
@Type(() => User)
author: User;
}
我 return,在 NestJs 服务器中由 class-transform
转换。
它被拦截器转换:
@Get()
@UseGuards(JwtAuthenticationGuard)
@UseInterceptors(MongooseClassSerializerInterceptor(Poker))
async findAll(@Req() req: RequestWithUser) {
return this.pokersService.findAll(req.user);
}
我不是拦截器的作者,但它是如何实现的:
function MongooseClassSerializerInterceptor(
classToIntercept: Type,
): typeof ClassSerializerInterceptor {
return class Interceptor extends ClassSerializerInterceptor {
private changePlainObjectToClass(document: PlainLiteralObject) {
if (!(document instanceof Document)) {
return document;
}
return plainToClass(classToIntercept, document.toJSON());
}
private prepareResponse(
response: PlainLiteralObject | PlainLiteralObject[],
) {
if (Array.isArray(response)) {
return response.map(this.changePlainObjectToClass);
}
return this.changePlainObjectToClass(response);
}
serialize(
response: PlainLiteralObject | PlainLiteralObject[],
options: ClassTransformOptions,
) {
return super.serialize(this.prepareResponse(response), options);
}
};
}
export default MongooseClassSerializerInterceptor;
我遇到的问题是,当我对控制器的 return 执行 console.log 时,我得到了这个:
[
{
_id: new ObjectId("61f030a9527e209d8cad179b"),
author: {
_id: new ObjectId("61f03085527e209d8cad1793"),
password: '--------------------------',
name: '----------',
email: '-------------',
__v: 0
},
title: 'Wonderfull first poker2',
__v: 0
}
]
但我得到这个 returned:
[
{
"_id": "61f5149643092051ba048c6e",
"author": {
"_id": "61f5149643092051ba048c6f",
"name": "----------",
"email": "-------------",
"__v": 0
},
"title": "Wonderfull first poker2",
"__v": 0
}
]
你查一下id,完全不一样。然后客户端会为这个 ID 请求一些数据,但什么也得不到。
知道我错过了什么吗?
此外,每次我发出 Get 请求时,我都会收到不同的返回值。
尝试将此用于 _id:
@Transform(params => params.obj._id)
或者更一般的情况:
@Transform(({ key, obj }) => obj[key])
遇到同样的问题,这样解决了。 params.obj 是原始对象。不幸的是,我不知道为什么 class-transformer 默认情况下没有正确定义 _id。
如果您想直接更改架构并且只使用 mongoose,则您有如下架构。
const mongoose = require('mongoose')
const mySchema = new mongoose.Schema({
field: String
}, {
toJSON: {
transform(doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
}
}
})
module.exports = mongoose.model("MySchema", mySchema)
但是,如果您使用的是 @nestjs/mongoose
,您的用法应该如下所示。
import { Document } from 'mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
export type MyDocument = MyClass & Document;
@Schema({
toJSON: {
transform(doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
},
},
})
export class MyClass {
@Prop()
field: string;
}
export const MySchema = SchemaFactory.createForClass(MyClass);
回想一下,在第一个示例中,new mongoose.Schema
函数的第一个参数是模式对象,第二个参数是模式选项。因此,@Schema
修饰符具有的 class 模式对象,它将包含的参数是模式选项!
我有以下 mongoDb class:
@Schema()
export class Poker {
@Transform(({ value }) => value.toString())
_id: ObjectId;
@Prop()
title: string;
@Prop({ type: mongoose.Schema.Types.ObjectId, ref: User.name })
@Type(() => User)
author: User;
}
我 return,在 NestJs 服务器中由 class-transform
转换。
它被拦截器转换:
@Get()
@UseGuards(JwtAuthenticationGuard)
@UseInterceptors(MongooseClassSerializerInterceptor(Poker))
async findAll(@Req() req: RequestWithUser) {
return this.pokersService.findAll(req.user);
}
我不是拦截器的作者,但它是如何实现的:
function MongooseClassSerializerInterceptor(
classToIntercept: Type,
): typeof ClassSerializerInterceptor {
return class Interceptor extends ClassSerializerInterceptor {
private changePlainObjectToClass(document: PlainLiteralObject) {
if (!(document instanceof Document)) {
return document;
}
return plainToClass(classToIntercept, document.toJSON());
}
private prepareResponse(
response: PlainLiteralObject | PlainLiteralObject[],
) {
if (Array.isArray(response)) {
return response.map(this.changePlainObjectToClass);
}
return this.changePlainObjectToClass(response);
}
serialize(
response: PlainLiteralObject | PlainLiteralObject[],
options: ClassTransformOptions,
) {
return super.serialize(this.prepareResponse(response), options);
}
};
}
export default MongooseClassSerializerInterceptor;
我遇到的问题是,当我对控制器的 return 执行 console.log 时,我得到了这个:
[
{
_id: new ObjectId("61f030a9527e209d8cad179b"),
author: {
_id: new ObjectId("61f03085527e209d8cad1793"),
password: '--------------------------',
name: '----------',
email: '-------------',
__v: 0
},
title: 'Wonderfull first poker2',
__v: 0
}
]
但我得到这个 returned:
[
{
"_id": "61f5149643092051ba048c6e",
"author": {
"_id": "61f5149643092051ba048c6f",
"name": "----------",
"email": "-------------",
"__v": 0
},
"title": "Wonderfull first poker2",
"__v": 0
}
]
你查一下id,完全不一样。然后客户端会为这个 ID 请求一些数据,但什么也得不到。
知道我错过了什么吗?
此外,每次我发出 Get 请求时,我都会收到不同的返回值。
尝试将此用于 _id:
@Transform(params => params.obj._id)
或者更一般的情况:
@Transform(({ key, obj }) => obj[key])
遇到同样的问题,这样解决了。 params.obj 是原始对象。不幸的是,我不知道为什么 class-transformer 默认情况下没有正确定义 _id。
如果您想直接更改架构并且只使用 mongoose,则您有如下架构。
const mongoose = require('mongoose')
const mySchema = new mongoose.Schema({
field: String
}, {
toJSON: {
transform(doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
}
}
})
module.exports = mongoose.model("MySchema", mySchema)
但是,如果您使用的是 @nestjs/mongoose
,您的用法应该如下所示。
import { Document } from 'mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
export type MyDocument = MyClass & Document;
@Schema({
toJSON: {
transform(doc, ret) {
ret.id = ret._id;
delete ret._id;
delete ret.__v;
},
},
})
export class MyClass {
@Prop()
field: string;
}
export const MySchema = SchemaFactory.createForClass(MyClass);
回想一下,在第一个示例中,new mongoose.Schema
函数的第一个参数是模式对象,第二个参数是模式选项。因此,@Schema
修饰符具有的 class 模式对象,它将包含的参数是模式选项!