1

我正在尝试使用 Mikro-orm 制作 Graphql 服务器并遇到问题。

这是我的 Product.ts 实体;

    import {
      Entity,
      IdentifiedReference,
      ManyToOne,
      PrimaryKey,
      Property
    } from '@mikro-orm/core'
    import { Field, Float, ObjectType } from 'type-graphql'
    import { ProductArguments } from '../util/types'
    import { Category } from './Category'
    
    @Entity()
    @ObjectType()
    export class Product {
      constructor({ title, price, description }: ProductArguments) {
        this.title = title
        this.price = price
        this.description = description
      }
    
      @Field()
      @PrimaryKey()
      id!: number
    
      @Field()
      @Property()
      title!: string
    
      @Field()
      @Property()
      imageUrl!: string
    
      @Field(() => Float)
      @Property({ type: 'decimal' })
      price!: number
    
      @Field(() => String)
      @Property({ type: 'text' })
      description!: string
    
      @Field(() => Category)
      @ManyToOne(() => Category)
      category!: IdentifiedReference<Category>
    
      @Field()
      @Property()
      createdAt: Date = new Date()
    
      @Field()
      @Property({ onUpdate: () => new Date() })
      updatedAt: Date = new Date()
    }

这是我的 Category.ts 实体

  import {
    Cascade,
      Collection,
      Entity,
      LoadStrategy,
      OneToMany,
      PrimaryKey,
      Property
    } from '@mikro-orm/core'
    import { Field, ObjectType } from 'type-graphql'
    import { Product } from './Product'
    
    @Entity()
    @ObjectType()
    export class Category {
      constructor(title: string) {
        this.title = title
      }
    
      @Field()
      @PrimaryKey()
      id!: number
    
      @Field()
      @Property()
      title!: string
    
      @Field(() => [Product])
      @OneToMany({
        entity: () => Product,
        mappedBy: (product) => product.category,
        cascade: [Cascade.REMOVE],
        strategy: LoadStrategy.JOINED
      })
      products = new Collection<Product>(this)
    
      @Field()
      @Property()
      createdAt: Date = new Date()
    
      @Field()
      @Property({ onUpdate: () => new Date() })
      updatedAt: Date = new Date()
    }

基本上,我与类别和产品是一对多的关系。每个产品应该属于一个类别,一个类别可以有多个产品。

现在在我的解析器中,我正在尝试使用以下内容获取所有类别。

   const categories = await em
      .createQueryBuilder(Category)
      .select('*')
      .getResult()
    return em.populate(categories, ['products'])

这工作得很好。没有错误。但是,当我尝试获取具有以下类别的所有产品时:

   const products = await em
      .createQueryBuilder(Product)
      .select('*')
      .getResult()
    return em.populate(products, ['category'])

或左连接

   return em
      .createQueryBuilder(Product, 'p')
      .select('*')
      .leftJoinAndSelect('p.category', 'c')
      .getResultList()

我收到以下错误这是生成的查询。

选择 "p".*, "c"."id" 作为 "c__id", "c"."title" 作为 "c__title", "c"."created_at" 作为 "c__created_at", "c"."updated_at" as "c__updated_at" from "product" as "p" left join "category" as "c" on "p"."category_id" = "c"."id"```

我还尝试在数据库中运行此查询,并得到了我想要的实际结果。但是在graphql中,我收到以下错误。我在这里做错了什么?

  {
      "message": "Cannot return null for non-nullable field Category.title.",
      "locations": [
        {
          "line": 11,
          "column": 7
        }
      ],
      "path": [
        "products",
        0,
        "category",
        "title"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: Cannot return null for non-nullable field Category.title.",
4

1 回答 1

0

对于和我有同样问题的人,看看这行

  @Field(() => Category)
  @ManyToOne(() => Category)
  category!: IdentifiedReference<Category>

如果没有先正确理解它,我不应该包含 IdentifiedReference。从文档中,

IdentifiedReference 是一种将主键属性添加到 Reference 接口的交集类型。它允许直接从 Reference 实例中获取主键。

基本上这里发生的事情是我得到了产品表主键的引用。但我正在从中访问 title 属性。有一个getProperty函数可以从中获取属性/数据库字段。但是像下面这样替换代码解决了我的问题。

  @Field(() => Category)
  @ManyToOne(() => Category)
  category!: Category

您可以在此处关注我们的 github讨论

于 2021-11-25T15:42:03.713 回答