Hasura GraphQL嵌套对象UPSERT Mutation如何将Person对象纳入变量而非硬编码
错误写法的根因
之前的写法触发两条独立插入操作的核心原因,是对Hasura嵌套插入的objects参数结构理解有偏差:
insert_<主表>的objects参数,数组内的每一个元素对应一条完整的主表插入记录,只有处于同一个对象层级下的字段,才会被识别为「主表字段+嵌套关联子表写入」的绑定关系- 之前把
$person作为数组第一个元素、把关联地址对象作为数组第二个元素,本质是让Hasura执行两条互不相关的主表插入:第一条只写入主表字段、不带任何关联子表配置;第二条是无主字段的空主表记录、仅带关联地址配置,完全无法实现主表与子表的绑定写入。
修正后的实现方案
要完全复现原硬编码版本的upsert效果,无需硬编码任何主表字段,只需要把主表字段和嵌套关联配置合并到同一个插入对象中,通过GraphQL对象展开语法传入主表字段变量即可。
修正后的Mutation代码
mutation insertPerson( $person: person_insert_input! $address: [adr_insert_input!]! $emails: [emails_insert_input!]! ) { insert_info( objects: [ { # 展开传入的person主表字段变量 ...$person # 完全保留原版本的嵌套关联子表写入配置 address: { data: $address on_conflict: { constraint: person_id_pk update_column: [add_text_line1, zip_code] } } emails: { data: $emails on_conflict: { constraint: person_id_pk update_column: [email_text] } } } ] # 完全保留原版本的主表upsert冲突配置 on_conflict: { constraints: person_pk update_columns: [f_name, l_name] } ) { affected_rows } }
配套变量结构
将原硬编码在Mutation中的f_name、l_name全部挪入person变量,其余关联子表的变量结构与原实现保持一致:
{ "person": { "f_name": "User1", "l_name": "Test" }, "address": [ { "add_text_line1": "123 Main Street", "zip_code": 50501 } ], "emails": [ { "email_text": "FirstLastName@email.com" } ] }
避坑提醒
- 不要将
$person和嵌套关联配置拆为objects数组的独立元素,必须保证所有主表字段、嵌套关联逻辑处于同一个对象层级 - 对象展开
...$person需写在主表插入对象的顶层,不能放到子表的data数组内部,否则会被识别为子表字段 - 原实现中所有
on_conflict配置(主表冲突规则、每个关联子表的冲突规则)必须完整保留,不能因为改用变量传主字段就删除,否则会丢失原有的upsert更新能力 - 传入
$person变量时,不要在对象内部嵌套定义address、emails字段,这部分关联逻辑是在Mutation结构中单独声明的,避免重复定义导致的配置冲突
内容的提问来源于stack exchange,提问作者Saher
相关产品推荐
相关产品推荐

