如何使用 graphql 定义 upsert(如果存在则更新否则插入)?

问题描述 投票:0回答:3

我希望能够发送单个 graphql 文档来添加一条记录(如果指定的条件不存在),或者如果指定的条件与现有条件匹配,则更新(部分或全部非 ident/非 PK/非 NK 字段)现有记录记录一下。

我可以在传统 SQL 方言和 ElasticSearch(通过查询更新)中通过几种方式做到这一点。但我不明白它应该如何在 graphql 中指定或描述 - 或者它是否可能。

在规范和网络上有一些添加记录的示例,这些示例似乎需要将看起来像“额外”或“很好有”(如架构/类型定义)的内容包含在文档中。更新示例通常具有不匹配的字段、参数和变量名称(如 Author.Id 和authorId),或者使用非 graphql 特定语言(如 Javascript)编写(与“Author”相同的示例页面。)来自最终客户端的两阶段操作似乎也不是正确的方法,因为只有目标数据存储才会知道采取哪个操作是正确的。

对于我正在开发的多租户 API,不会有固定的预定义集中模式,并且每个租户可能对类型有不同的定义(例如租户 A 有一个包含 16 个字段的合同实体,但租户 B有一个具有相同名称和预期功能的类型,有 20 个字段。两者将共享相同的合约存储空间。

我所要求的有可能吗?如果可以的话可以分享一个例子吗?

graphql upsert
3个回答
1
投票

upsert 不能替代更新

...那么这可能是一个宽松的解释...

createItem
(如果您愿意,请将其命名为
upsertItem
)突变解析器可以插入或更新(BE,解析器实现/存储/数据库相关决策),使用或不使用严格/显式输入类型定义(创建时必需,对于更新)

...对于相同的突变,租户可以有不同的输入类型(字段数量)

...在 wp-graphql (WordPress) 中,它甚至是基于角色的 - 不同的内省结果、不同的字段参数、不同的可用突变...但它来自动态、非持久/无状态的 php 字符

您可以通过抛出错误(当输入与特定用法/租户不匹配时 - 例如,在解析器内部或中间件中的某些验证“层”中限制字段使用(每个租户)或类型匹配(必需/不需要)。对于某些字段返回“必需的错误”,而类型定义中的所有字段都是可选的)。当内省查询被阻止(在生产中)时,这只是一个文档问题(不是自我描述)。

更新 - 示例

如果要更新插入的目标实体是具有 ID、名字和姓氏的人员(需要 ID 和姓氏)

ID

这里不能要求...

UpsertPersonInput

,所有(
ID
First
Last
)可选...

对于创建upsertPerson( $input: UpsertPersonInput) {..

,具有创建所需的变量(根据验证规则)(
First: "some", Last: "Name"
)

...

ID

此处未知,已创建并作为结果返回

...没有提供

ID

,然后假设“创建模式”

对于更新:查询相同,但当提供带有 input

 道具验证的 
ID
 变量时,验证在“更新模式”下工作(至少一个其他变量 - 
input
 道具 - 必需,例如 
Last
 ...或其他附加验证规则)

...虽然只提供了

input.ID

 属性>抛出一些“不需要在输入参数中传递“第一个””(任何字段)错误...就像在单独的更新突变及其输入类型中一样。


0
投票
答案是……你不知道。除了解析器的总体概念之外,没有任何语法或文法可以在 GraphQL 中指定或表达更新行为,为此您必须完全创建自己的语法。对我来说,这解决了不完整的查询语言。

目前我无法理解为什么这种差距继续存在,但就这个问题而言,在更新方面答案是令人失望的“否”。


0
投票
当您必须在更新中提供所有字段时,就没有自由,否则在使用 GraphQL 时它们将被设置为 NULL。当你有如下表时就没有自由: 表 1(ID 号 PK 不为空、名字 VARCHAR2(20)、姓氏 VARCHAR2(20)、公司 VARCHAR2(25)、状态 VARCHAR2(10) )

在 Oracle 或任何其他数据库中,我可以轻松更新满足条件的所有记录的状态 更新表1 设置状态=“完成” 其中公司 = 'XYZ 公司';

但在 GraphQL 中,我必须在更新中提供 ID,否则会收到错误“需要 ID...”,或者必须包含表中的所有列 这是非常低效的。

© www.soinside.com 2019 - 2024. All rights reserved.