如何在Hasura GQL变更中使用带条件逻辑的模板字面量
问题核心原因
GraphQL 规范本身不支持在操作语句内部基于传入变量动态增删输入对象的字段,你尝试的模板字符串写法无法生效的核心原因有两个:
$vendorLicenseId是 GraphQL 层的请求变量,只会在请求发送到 Hasura 引擎时才会被解析,JS 解析gql模板字符串生成查询AST的阶段完全拿不到这个变量的值,模板内的判断逻辑根本不会按预期执行- GraphQL 查询的结构必须在发送给服务端前是固定合法的,输入对象位置不支持
@skip/@include这类条件指令(这类指令仅能用于返回结果的选择集字段),无法在语句内部实现字段省略逻辑
可行实现方案
方案1:JS层动态拼接查询结构(最贴合你的需求,无额外依赖)
把条件判断逻辑移到gql标签外部,根据是否存在vendorLicenseId动态生成对应结构的合法查询,变量仍然走标准GraphQL变量传参,不存在注入风险。
代码示例:
// 动态生成对应mutation export const generateLicenseMutation = (hasVendorLicenseId) => { const licenseObject = hasVendorLicenseId ? ` id: $vendorLicenseId vendor_id: $vendorId license_id: $licenseId ` : ` vendor_id: $vendorId license_id: $licenseId `; return gql` mutation UpdateLicense( $vendorId: Int! $licenseId: Int! $vendorLicenseId: Int ) { insert_license_one( object: { ${licenseObject} } on_conflict: { constraint: license_pkey update_columns: [license_number, license_id] } ) { id license_id vendor_id license_number } } `; }; // 调用示例 const variables = { vendorId: 1, licenseId: 2, // 有id则传,无id则不传该字段 // vendorLicenseId: 123 }; const mutation = generateLicenseMutation(!!variables.vendorLicenseId); // 正常执行mutate逻辑即可
这种方案完全匹配你需要的upsert逻辑:传id时走主键冲突更新,不传id时走新数据插入,Hasura会自动调用id字段的默认值(比如自增序列)生成新主键,不会触发非空约束报错。两种结构的查询会被Hasura分别做查询缓存,不会有额外性能损耗。
方案2:拆分插入/更新为两个独立mutation(更易维护,适合复杂场景)
如果不想动态拼接查询,可以直接拆成两个语义明确的mutation:
- 新增场景:用
insert_license_one,不传id字段 - 更新场景:用
update_license_by_pk,传入id作为匹配条件
业务逻辑层判断是否存在vendorLicenseId,调用对应mutation即可,代码可读性更高,适合字段较多、逻辑复杂的场景。
注意避坑
不要尝试在输入对象字段上使用@skip/@include指令,这不符合GraphQL语法规范,会直接被Hasura引擎报语法错误。
内容的提问来源于stack exchange,提问作者friendlyfire
相关产品推荐
相关产品推荐

