【问题标题】:ParseObjectIdPipe for MongoDB's ObjectID为 MongoDB ObjectID 解析对象 ID 管道
【发布时间】:2020-06-03 18:34:14
【问题描述】:

我想用 TypeORM 和 MongoDB 创建一个 NestJs API。我的实体 ID 字段的类型为 ObjectID。控制器路由应该在将传入的 id 传递给服务之前验证它们。我知道 Nest 附带 ParseIntPipe 和 ParseUUIDPipe 但据我所知,我没有什么可以用于 MongoDB ObjectID。

所以我为这些字段创建了自己的管道,如此处所述https://docs.nestjs.com/pipes#transformation-use-case

import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
import { ObjectID } from 'typeorm';

@Injectable()
export class ParseObjectIdPipe implements PipeTransform<any, ObjectID> {
  transform(value: any): ObjectID {
    const validObjectId: boolean = ObjectID.isValid(value);

    if (validObjectId) {
      throw new BadRequestException('Invalid ObjectId');
    }

    const objectId: ObjectID = ObjectID.createFromHexString(value);
    return objectId;
  }
}

并希望这能解决问题,即使是边缘情况。我可以将它用于我的路由参数,例如

  @Get(':id')
  public getUserById(@Param('id', ParseObjectIdPipe) id: ObjectID): Promise<User> {
    return this.usersService.getUserById(id);
  }

我遇到的问题是某些路由需要Body 验证。我使用这里描述的类验证器包

https://docs.nestjs.com/techniques/validation

看来我必须为那些ObjectID 字段创建自己的类验证器装饰器,但这应该没问题。也许我会在这里找到一些关于如何做到这一点的东西https://github.com/typestack/class-validator#custom-validation-classes。但是如何将这些字段转换为ObjectID 类型?我以后也可以使用自定义管道吗?


更新:

我还尝试通过 class-transformer 包转换值。所以这个代码是

import { ObjectID } from 'typeorm';
import { Type, Transform } from 'class-transformer';
import { BadRequestException } from '@nestjs/common';

export class FooDTO {
  @Type(() => ObjectID)
  @Transform(bar => {
    if (ObjectID.isValid(bar)) {
      throw new BadRequestException('Invalid ObjectId');
    }

    return ObjectID.createFromHexString(bar);
  })
  public bar: ObjectID;
}

不幸的是,bar 的值始终是undefined。但也许这段代码可能有助于验证和转换目的......

【问题讨论】:

    标签: mongodb nestjs typeorm class-validator


    【解决方案1】:

    所以对于Body 验证,我可以从这里使用IsMongoId() 装饰器

    https://github.com/typestack/class-validator#manual-validation

    验证看起来像

    import { IsMongoId } from 'class-validator';
    import { ObjectID } from 'typeorm';
    
    export class FooDTO {
      @IsMongoId()
      public bar: ObjectID;
    }
    

    【讨论】:

      【解决方案2】:

      由于您从错误的库中导入,您得到了未定义。 你需要改变这个:

      import { ObjectID } from 'typeorm';
      

      为此:

      import { ObjectID } from 'mongodb';
      

      【讨论】:

        【解决方案3】:

        我拿走了您的代码并更改了一些部分。我测试了一下,效果很好。

        import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';
        import { Types } from 'mongoose';
        
        @Injectable()
        export class ParseObjectIdPipe implements PipeTransform<any, Types.ObjectId> {
            transform(value: any): Types.ObjectId {
                const validObjectId = Types.ObjectId.isValid(value);
        
                if (!validObjectId) {
                    throw new BadRequestException('Invalid ObjectId');
                }
        
                return Types.ObjectId.createFromHexString(value);
            }
        }
        

        【讨论】:

        • 如果您的更改解决了问题,请说明这些更改是什么。实际上,您的答案看起来像是评论,而不是答案。
        【解决方案4】:

        对于类转换器方法,这对我有用

        import { IsNotEmpty } from "class-validator";
        import { Type, Transform } from 'class-transformer';
        import { Types } from "mongoose"
        
        export class CreateCommentDto {
        
            @IsNotEmpty()
            @Type(() => Types.ObjectId)
            @Transform(toMongoObjectId)
            articleId: Types.ObjectId
        

        使用 'toMongoObjectId' 的定义:

        export function toMongoObjectId({ value, key }): Types.ObjectId {
            if ( Types.ObjectId.isValid(value) && ( Types.ObjectId(value).toString() === value)) {
                return Types.ObjectId(value);
            } else {
                throw new BadRequestException(`${key} is not a valid MongoId`);
            }
        }
        

        【讨论】:

          【解决方案5】:

          只需使用以下代码在代码中创建对象 id 的管道:

          import { PipeTransform, Injectable, BadRequestException } from 
          '@nestjs/common';
          import { ObjectID } from 'mongodb';
          
          @Injectable()
          export class ParseObjectIdPipe implements PipeTransform<any, ObjectID> {
          
          public transform(value: any): ObjectID {
          try {
            const transformedObjectId: ObjectID = ObjectID.createFromHexString(value);
            return transformedObjectId;
          } catch (error) {
            throw new BadRequestException('Validation failed (ObjectId is expected)');
          }
          }
          }
          

          并在控制器方法中添加 piple:

          @Post('cat/:id')
          async cat(
          @Param('id', ParseObjectIdPipe) id: ObjectId,
          @Res() res,
          @Body() cat: catDTO[],)
          

          【讨论】:

            猜你喜欢
            • 2016-09-12
            • 2021-02-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-20
            • 1970-01-01
            相关资源
            最近更新 更多