【问题标题】:How to have class-transform converting properly the _id of a mongoDb class?如何让类转换正确转换 mongoDb 类的 _id?
【发布时间】:2022-05-09 21:25:23
【问题描述】:

我有以下 mongoDb 类:

@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;
}

我返回,在 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;

我遇到的问题是,当我对控制器的返回执行 console.log 时,我得到了这个:

[
  {
    _id: new ObjectId("61f030a9527e209d8cad179b"),
    author: {
      _id: new ObjectId("61f03085527e209d8cad1793"),
      password: '--------------------------',
      name: '----------',
      email: '-------------',
      __v: 0
    },
    title: 'Wonderfull first poker2',
    __v: 0
  }
]

但我得到了返回:

[
    {
        "_id": "61f5149643092051ba048c6e",
        "author": {
            "_id": "61f5149643092051ba048c6f",
            "name": "----------",
            "email": "-------------",
            "__v": 0
        },
        "title": "Wonderfull first poker2",
        "__v": 0
    }
]

如果您检查 id,它根本不一样。然后客户端会向这个 ID 询问一些数据,但什么也没有收到。

知道我错过了什么吗?

此外,每次我发出 Get 请求时,我都会收到不同的返回值。

【问题讨论】:

    标签: mongodb mongoose nestjs class-transformer


    【解决方案1】:

    尝试将此用于_id:

    @Transform(params => params.obj._id)
    

    或者这是更一般的情况:

    @Transform(({ key, obj }) => obj[key])
    

    遇到同样的问题,就这样解决了。 params.obj 是一个原始对象。不幸的是,我不知道为什么 class-transformer 默认没有正确定义 _id。

    【讨论】:

    • 你好,谢谢你的回答,我其实和你一样结束了:@Transform((value) => value.obj._id.toString())
    【解决方案2】:

    如果您想直接更改架构并且只使用 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 decarator 所具有的类模式对象,它将包含的参数是 Schema 选项!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 2022-01-05
      相关资源
      最近更新 更多