Amplify push GraphQL schema 指令参数报错解决方案
问题场景
跟随YouTube在线售书平台开发教程开发订单模块GraphQL schema时,因Amplify GraphQL语法随版本迭代更新,尝试将旧版@connection、@key写法迁移至新版官方规范后,执行amplify push持续触发schema校验错误。因首次接触GraphQL与AWS技术栈,自行排查修复部分问题后仍有残留错误无法解决,导致项目阻塞。
原始编写的GraphQL Schema
type Book @model(subscriptions: null) @auth( rules: [ #allow admins to create, update and delete books { allow: groups, groups: ["Admin"] } # allow all authenticated users to view books { allow: private, operations: [read] } # allow all guest users (not authenticated) to view books { allow: public, operations: [read] } ] ) { id: ID! title: String! description: String image: String author: String featured: Boolean price: Float orders: [BookOrder] @hasOne(keyName: "byBook", fields: ["id"]) } type BookOrder @model(queries: null, subscriptions: null) #@key(name: "byBook", fields: ["book_id", "order_id"]) #@key(name: "byOrder", fields: ["order_id", "book_id"]) @auth( rules: [ # allow admins to create bookorders for customers by using customer email in lambda { allow: owner, identityClaim: "email", ownerField: "customer" } { allow: groups, groups: ["Admin"] } ] ) { id: ID! book_id: ID! @index(name: "byBook", sortKeyFields: ["book_id, order_id"]) order_id: ID! @index(name: "byOrder", sortKeyFields: ["order_id, book_id"]) book: Book @hasOne(fields: ["book_id"]) order: Order @hasOne(fields: ["order_id"]) } type Order @model(subscriptions: null) @auth( rules: [ # only owner can see his orders { allow: owner, identityClaim: "email", ownerField: "customer" } #allow admins to view orders { allow: groups, groups: ["Admin"] } ] ) #@key(name: "byUser", fields: ["user"]) { id: ID! user: String! @index(name: "byUser", sortKeyfields: ["user"]) date: String total: Float books: [BookOrder] @manyToMany(keyName: "byOrder", fields: ["id"]) } enum OrderStatus { SUCCESS FAILED } input CartItem { id: ID! title: String image: String price: Float amount: Int } input ProcessOrderInput { id: ID! cart: [CartItem] total: Float! token: String! address: String } type Mutation { processOrder(input: ProcessOrderInput!): OrderStatus @function(name: "processPayment-${env}") @function(name: "createOrder-${env}") }
amplify push 原始报错信息
An error occurred when pushing the resources to the cloud 🛑 An error occurred during the push operation: / Schema validation failed. Unknown argument "keyName" on directive "@hasOne". GraphQL request:21:31 20 | price: Float 21 | orders: [BookOrder] @hasOne(keyName: "byBook", fields: ["id"]) | ^ 22 | } Unknown argument "sortKeyfields" on directive "@index". Did you mean "sortKeyFields"? GraphQL request:56:40 55 | id: ID! 56 | user: String! @index(name: "byUser", sortKeyfields: ["user"]) | ^ 57 | date: String Unknown argument "keyName" on directive "@manyToMany". GraphQL request:59:34 58 | total: Float 59 | books: [BookOrder] @manyToMany(keyName: "byOrder", fields: ["id"]) | ^ 60 | } Unknown argument "fields" on directive "@manyToMany". GraphQL request:59:54 58 | total: Float 59 | books: [BookOrder] @manyToMany(keyName: "byOrder", fields: ["id"]) | ^ 60 | } Directive "@manyToMany" argument "relationName" of type "String!" is required, but it was not provided. GraphQL request:59:22 58 | total: Float 59 | books: [BookOrder] @manyToMany(keyName: "byOrder", fields: ["id"]) | ^ 60 | } ⚠️ Schema validation failed, please check directive usage against official specifications
错误根因与修复方案
所有报错均为新版Amplify GraphQL Transformer v2的指令用法不匹配导致,逐个修复点如下:
- 关系指令用法错误:
- Book与BookOrder是一对多关系,不支持用
@hasOne,且新版@hasMany/@hasOne没有keyName参数,关联索引用indexName参数指定。Book下的orders字段应改为@hasMany(indexName: "byBook", fields: ["id"]) - 已经手动定义了中间关联表
BookOrder,不需要使用@manyToMany(该指令仅用于Amplify自动生成中间连接表的场景,必须传relationName参数),Order与BookOrder也是一对多关系,Order下的books字段应改为@hasMany(indexName: "byOrder", fields: ["id"]) - 子表
BookOrder持有外键关联父表,不能用@hasOne,要改用@belongsTo指定关联外键:book: Book @belongsTo(fields: ["book_id"])、order: Order @belongsTo(fields: ["order_id"])
- Book与BookOrder是一对多关系,不支持用
@index指令用法错误:- 参数拼写错误:
sortKeyfields改为驼峰命名sortKeyFields sortKeyFields参数必须传入字段名数组,不能传逗号拼接的字符串;且加@index的字段本身是分区键,不需要重复放在sortKey列表中:book_id上的byBook索引,分区键为book_id,排序键为order_id,写法改为@index(name: "byBook", sortKeyFields: ["order_id"])order_id上的byOrder索引,分区键为order_id,排序键为book_id,写法改为@index(name: "byOrder", sortKeyFields: ["book_id"])
- Order下
user字段的byUser索引,分区键为user,不需要将自身作为排序键,可直接写@index(name: "byUser"),如需按查询排序可将date作为排序键:@index(name: "byUser", sortKeyFields: ["date"])
- 参数拼写错误:
- 隐式字段缺失:
@auth规则中指定了ownerField: "customer",需要在BookOrder和Order类型中补充customer: String字段,否则会触发字段不存在的校验错误。
修复后可正常推送的完整Schema
type Book @model(subscriptions: null) @auth( rules: [ { allow: groups, groups: ["Admin"] } { allow: private, operations: [read] } { allow: public, operations: [read] } ] ) { id: ID! title: String! description: String image: String author: String featured: Boolean price: Float orders: [BookOrder] @hasMany(indexName: "byBook", fields: ["id"]) } type BookOrder @model(queries: null, subscriptions: null) @auth( rules: [ { allow: owner, identityClaim: "email", ownerField: "customer" } { allow: groups, groups: ["Admin"] } ] ) { id: ID! customer: String book_id: ID! @index(name: "byBook", sortKeyFields: ["order_id"]) order_id: ID! @index(name: "byOrder", sortKeyFields: ["book_id"]) book: Book @belongsTo(fields: ["book_id"]) order: Order @belongsTo(fields: ["order_id"]) } type Order @model(subscriptions: null) @auth( rules: [ { allow: owner, identityClaim: "email", ownerField: "customer" } { allow: groups, groups: ["Admin"] } ] ) { id: ID! customer: String user: String! @index(name: "byUser", sortKeyFields: ["date"]) date: String total: Float books: [BookOrder] @hasMany(indexName: "byOrder", fields: ["id"]) } enum OrderStatus { SUCCESS FAILED } input CartItem { id: ID! title: String image: String price: Float amount: Int } input ProcessOrderInput { id: ID! cart: [CartItem] total: Float! token: String! address: String } type Mutation { processOrder(input: ProcessOrderInput!): OrderStatus @function(name: "processPayment-${env}") @function(name: "createOrder-${env}") }
内容的提问来源于stack exchange,提问作者Aiden
相关产品推荐
相关产品推荐

