如何在单个GraphQL突变中插入查询获取的默认值?
在Hasura单个GraphQL突变中用查询结果作为默认值的方案
当然可以做到!而且完全不需要分两次REST调用——Hasura结合PostgreSQL的原子性特性,能帮你在单个突变里完成查询+插入的操作,完美保证数据一致性。下面给你两种实用的方案:
方案一:直接在Insert突变中嵌入子查询
这是最直接的方式,你可以在插入字段的值位置直接写子查询,Hasura会把整个操作作为单个PostgreSQL事务执行,确保原子性。
把你的突变语句修改成这样:
mutation insertCode($code: String = "", $workcenter: String = "") { insert_code_tracing(objects: { code: $code, workcenter: $workcenter, # 直接嵌入子查询获取对应workcenter的最新order order: ( select orders.order where: { workcenter: {_eq: $workcenter} } order_by: {time: desc_nulls_last} limit: 1 ) }) { returning { time order workcenter } } }
关键注意点:
- 确保当前操作的角色拥有
orders表的select权限,以及code_tracing表的insert权限,否则子查询会执行失败。 - 如果存在子查询返回空值的情况(比如没有匹配的workcenter),可以用
coalesce函数设置默认值,避免插入失败:order: coalesce( (select orders.order where: { workcenter: {_eq: $workcenter} } order_by: {time: desc_nulls_last} limit: 1), "NO_ACTIVE_ORDER" # 这里替换成你想要的默认值 )
方案二:用PostgreSQL函数封装逻辑(适合复杂场景)
如果你的业务逻辑更复杂(比如需要额外的校验、多表关联处理),可以把逻辑封装成PostgreSQL函数,再通过Hasura暴露为突变。
步骤1:创建PostgreSQL函数
CREATE OR REPLACE FUNCTION insert_code_tracing_with_active_order( p_code text, p_workcenter text ) RETURNS SETOF code_tracing AS $$ BEGIN RETURN QUERY INSERT INTO code_tracing(code, workcenter, "order") VALUES(p_code, p_workcenter, ( SELECT "order" FROM orders WHERE workcenter = p_workcenter ORDER BY time desc_nulls_last LIMIT 1 )) RETURNING *; END; $$ LANGUAGE plpgsql SECURITY DEFINER;
注意:如果
order是PostgreSQL的关键字,需要用双引号包裹。
步骤2:在Hasura中暴露函数为突变
在Hasura控制台的Data -> Functions页面,找到你创建的函数,开启"Expose as mutation"选项,然后就能在GraphQL中调用它:
mutation insertCode($code: String = "", $workcenter: String = "") { insert_code_tracing_with_active_order(p_code: $code, p_workcenter: $workcenter) { time order workcenter } }
这种方式的优势是把业务逻辑放在数据库层,更安全可控,同时依然保持原子性。
内容的提问来源于stack exchange,提问作者morphineglelly
相关产品推荐
相关产品推荐

