无法为 mikro orm graphql 中的不可空字段返回 null
Posted
技术标签:
【中文标题】无法为 mikro orm graphql 中的不可空字段返回 null【英文标题】:Cannot return null for non-nullable field in mikro orm graphql 【发布时间】:2022-01-02 12:45:54 【问题描述】:我正在尝试使用 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.",
【问题讨论】:
这是什么意思? 在返回之前从 DB 记录数据 ... category 属性应该是一个带有 title 字段的对象,它是空/null/undefined ...你在学习一些教程吗? graphql 不应过度获取,产品解析器应仅返回产品字段,“缺失”类别值 [如果请求] 应调用单独的字段解析器以读取相关类别数据(父/根/第一个 arg - 已解析的产品对象 - 包含 category_id,可以用于类别数据库读取)...当然,您可以过度获取 [以优化数据库读取],但以有限的可扩展性为代价 【参考方案1】:对于和我有同样问题的人,看看这几行
@Field(() => Category)
@ManyToOne(() => Category)
category!: IdentifiedReference<Category>
如果没有先正确理解它,我不应该包含 IdentifiedReference。从文档中,
IdentifiedReference 是一种将主键属性添加到 Reference 接口的交集类型。它允许直接从 Reference 实例中获取主键。
基本上这里发生的事情是我获得了产品表主键的引用。但我正在从中访问 title 属性。有一个getProperty
函数可以从中获取属性/数据库字段。但是像下面这样替换代码解决了我的问题。
@Field(() => Category)
@ManyToOne(() => Category)
category!: Category
您可以在此处关注我们的 github discussion。
【讨论】:
以上是关于无法为 mikro orm graphql 中的不可空字段返回 null的主要内容,如果未能解决你的问题,请参考以下文章