ParseObjectIdPipe 获取 MongoDB 的 ObjectID

7 mongodb typeorm class-validator nestjs

我想使用 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我遇到的问题是某些路线需要Body验证。我使用类验证器包,如此处所述

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

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


更新:

我还尝试通过类转换器包来转换值。所以这个的代码是

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;
}
Run Code Online (Sandbox Code Playgroud)

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

小智 8

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您的更改解决了问题,请具体说明这些更改是什么。事实上,您的答案看起来像是评论,而不是答案。 (2认同)

小智 8

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

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
Run Code Online (Sandbox Code Playgroud)

'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`);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 1

您未定义,因为您从错误的库导入。你需要改变这个:

import { ObjectID } from 'typeorm';
Run Code Online (Sandbox Code Playgroud)

为了这:

import { ObjectID } from 'mongodb';
Run Code Online (Sandbox Code Playgroud)