如何在数据库中定义一个Json类型的Prisma字段,并将其Map到一个已定义的TypeGraphQL对象?

e4eetjau  于 2022-11-26  发布在  其他
关注(0)|答案(1)|浏览(161)

我想在schema.prisma文件中创建一个Json?类型的字段,但我想将其Map到TypeGraphQL @ObjectType()类。我不想在数据库中为该对象创建一个表。我想将其作为json存储在db中,但我想确保它符合我在gql模式中定义的类型。这可能吗?我没有使用typegraphql-prisma包。下面是一个简化的示例(这里的代码可能不完美,因为我无法复制/粘贴):
schema.prisma.comments中只有一个表是Json类型,而不是定义与Comment模型/表的一对多关系。
schema.prisma

model Post {
  id       Int     @id @default(autoincrement())
  title    String
  content  String
  comments Json?
}

但是在我的TypeGraphQL类型中,我想定义组成Comment的属性。我不想将comments定义为Prisma.JsonValue。我希望它是一个类似Comment[]的列表。
types.ts

@ObjectType()
export class Comment {
  @Field()
  id!:  number;

  @Field()
  content!: string;
}

@ObjectType()
export class Post {
  @Field()
  id!:  number;

  @Field()
  title!: string;

  @Field()
  content!: string;

  @Field((type) => [Comment], { nullable: true })
  comments?: Comment[] | null;
}

当我尝试查询时,我会收到不同的TypeScript错误,这取决于我尝试的不同操作。它不喜欢我在Prisma模型中使用JSON,而在comments的类型定义中使用对象。是否可以用这种方式定义我的数据库和类型?在对象和JSON之间“转换”的最佳方式是什么?谢谢!

import { Post as PostDb } from '@prisma/client';
import { Post } from './types.ts';

@Resolver(Post)
export class PostResolver {
  @Query((returns) => Post, { nullable: true })
  async getPostByTitle(title: string): Promise<PostDb | null> {
    try {
      return prismaClient.post.findUnique({
        where: { title }
      });
    } catch(error) {
      throw new GetPostError(error.message);
    }
  }
}
aiazj4mn

aiazj4mn1#

目前,据我所知,您必须使用class-transformer将普通的JSON转换为 type-graphqlclass的示例。

Comment

添加Expose装饰器,启用excludeExtraneousValues的使用:当将普通值转换为类时,应该从值中排除无关的属性。

// ...
import { Expose } from 'class-transformer';

@ObjectType()
export class Comment {
  @Field()
  @Expose()
  id!: number;

  @Field()
  @Expose()
  content!: string;
}

PostResolver

只要找到Prisma Post类,就使用实用函数mapPost将其Map到type-graphql类示例。
注意,对于每个JSON注解,我们使用class-transformer库中的函数plainToInstance将其转换为(type-graphql)Comment类的示例。

// ...
import type { Prisma, Post as PrismaPost } from '@prisma/client';
import { plainToInstance } from 'class-transformer';

@Resolver(Post)
export class PostResolver {
  /**
   * Map an instance of a Prisma Post class to
   *  an instance of a type-graphql class.
   *
   * @param post - Prisma Post class instance
   * @returns type-graphql Post class instance
   */
  private mapPost(post: PrismaPost): Post {
    return {
      ...post,
      comments: post.comments
        ? (post.comments as Prisma.JsonArray).map((comment) =>
            plainToInstance(Comment, comment, { excludeExtraneousValues: true })
          )
        : null
    };
  }

  @Query(() => Post, { nullable: true })
  async getPostByTitle(title: string): Promise<Post | null> {
    try {
      const post = prismaClient.post.findUnique({
        where: { title }
      });

      // Return null if post not found
      if (!post) return null;

      // Found! Map from Prisma to type-graphql
      return this.mapPost(post);
    } catch(error) {
      throw new GetPostError(error.message);
    }
  }
}

示例

假设您已将JSON Comment保存为:

[
  {
    "id": 0,
    "content": "Hello"
  },
  {
    "id": 1,
    "content": "World"
  }
]

现在您应该能够执行以下查询:

getPostByTitle(title: "Hello World") {
  id,
  comments {
    content
  }
}

得到如下结果:

{
  "data": {
    "getPostByTitle": {
      "id": 0,
      "comments": [
        {
          "content": "Hello"
        },
        {
          "content": "World"
        }
      ]
    }
  }
}

相关问题