我是GraphQL的新手,但我真的很喜欢。现在,我正在使用接口和联合,现在我面临着突变问题。
假设我有这个架构:
interface FoodType {
id: String
type: String
composition: [Ingredient]
}
type Pizza implements FoodType {
id: String
type: String
pizzaType: String
toppings: [String]
size: String
composition: [Ingredient]
}
type Salad implements FoodType {
id: String
type: String
vegetarian: Boolean
dressing: Boolean
composition: [Ingredient]
}
type BasicFood implements FoodType {
id: String
type: String
composition: [Ingredient]
}
type Ingredient {
name: String
qty: Float
units: String
}
现在,我想创建新的食物,所以我开始做这样的事情:
type Mutation {
addPizza(input:Pizza):FoodType
addSalad(input:Salad):FoodType
addBasic(input:BasicFood):FoodType
}
由于两个原因,此操作不起作用:
因此,我需要像这样修改以前的架构:
interface FoodType {
id: String
type: String
composition: [Ingredient]
}
type Pizza implements FoodType {
id: String
type: String
pizzaType: String
toppings: [String]
size: String
composition: [Ingredient]
}
type Salad implements FoodType {
id: String
type: String
vegetarian: Boolean
dressing: Boolean
composition: [Ingredient]
}
type BasicFood implements FoodType {
id: String
type: String
composition: [Ingredient]
}
type Ingredient {
name: String
qty: Float
units: String
}
type Mutation {
addPizza(input: PizzaInput): FoodType
addSalad(input: SaladInput): FoodType
addBasic(input: BasicInput): FoodType
}
input PizzaInput {
type: String
pizzaType: String
toppings: [String]
size: String
composition: [IngredientInput]
}
input SaladInput {
type: String
vegetarian: Boolean
dressing: Boolean
composition: [IngredientInput]
}
input BasicFoodInput {
type: String
composition: [IngredientInput]
}
input IngredientInput {
name: String
qty: Float
units: String
}
因此,在这里,我定义了我的3种制作披萨,色拉和基本食物的方法。我需要定义3种输入类型(每种食物一种),并且还需要为“成分”定义一种新的输入类型。
重复很多。那样你觉得可以吗?还是有更好的方法来解决这个问题?
谢谢
您可以做很多事情。例如,如果您要以编程方式声明架构,则可以避免如下所示:
const getPizzaFields = (isInput = false) => {
const fields = {
type: { type: GraphQLString }
pizzaType: { type: GraphQLString }
toppings: { type: new GraphQLList(GraphQLString) }
size: { type: GraphQLString }
composition: {
type: isInput ? new GraphQLList(IngredientInput) : new GraphQLList(Ingredient)
}
}
if (!isInput) fields.id = { type: GraphQLString }
return fields
}
const Pizza = new GraphQLObjectType({
name: 'Pizza',
fields: () => getFields()
})
const PizzaInput = new GraphQLObjectType({
name: 'Pizza',
fields: () => getFields(true)
})
或者,如果您的对象/输入遵循类似的模式,则您甚至可以编写一个用于从类型生成输入的函数:
const transformObject = (type) => {
const input = Object.assign({}, type)
input.fields.composition.type = new GraphQLList(IngredientInput)
delete input.fields.id
return input
}
另外,在使用定义架构时makeExecutableSchema
,您可以执行以下操作:
const commonPizzaFields = `
type: String
pizzaType: String
toppings: [String]
size: String
`
const schema = `
type Pizza {
id: String
${commonPizzaFields}
composition: [Ingredient]
}
input PizzaInput {
${commonPizzaFields}
composition: [IngredientInput]
}
`
所有这些方法的问题在于,尽管从技术上讲它们可能使您的代码更干燥,但它们也降低了模式的可读性,我认为这比复制本身更容易出错。
同样重要的是要理解,虽然从语法上讲,类型和输入类型可能看起来相同,但从功能上来看却不一样。例如,类型上的字段可能具有参数:
type Pizza {
toppings(filter: ToppingTypeEnum): [String]
}
输入类型字段没有参数,因此对于类型及其对应的输入类型中的toppings
字段,您将无法使用相同的语法。Pizza
PizzaInput
就个人而言,我会咬紧牙关,只写出您已经完成的类型和输入。我唯一会做的不同的事情是将它们分组在一起(列出您的类型而不是输入),以便可以轻松发现两者之间的任何差异。但是你的里程可能非常:)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句