我试图用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()
}
这是我的分类.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"标题";作为";c_ title"c"created_ at";作为";c_ created_ at"c"updated_ at";作为";c_ updated_at";从";产品";作为";p〃;左联接";类别";作为";c";关于";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.",
对于任何和我有同样问题的人,请查看
@Field(() => Category)
@ManyToOne(() => Category)
category!: IdentifiedReference<Category>
在没有正确理解IdentifiedReference之前,我不应该包含它。从文档来看,
IdentifiedReference是一种交集类型,它将主键属性添加到Reference接口。它允许直接从引用实例中获取主键。基本上,这里发生的事情是,我得到了一个带有产品表主键的引用。但是我正在从中访问title属性。有一个getProperty
函数可以从中获取属性/数据库字段。但是像下面这样替换代码解决了我的问题。
@Field(() => Category)
@ManyToOne(() => Category)
category!: Category
您可以在这里关注我们的github讨论。