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

How do you define an upsert (if exists update else insert) or even an update using graphql?

编辑:我将在这里给出 SQL 等价物,因为这是我传达我试图找到等价物的最简单方式。

person 的架构是

 id (system assigned clustered PK, probably a guid, doesnt really matter for this)
 FirstName : string
 LastName : string, required
 EmployeeCode : string, required, Unique

我希望能够在 GraphQL 中表示这样的查询(BEGIN/END 为简洁起见省略),并且只是 UPDATE 语句,我需要其中任何一个示例来显示如何定位特定记录,例如 WHERE子句。

IF EXISTS(SELECT TOP 1 1 FROM person WITH (UPDLOCK) WHERE EmployeeCode = 'ABC123')
   UPDATE person 
      SET FirstName = 'Mike'
          , LastName = 'Jones' 
   WHERE EmployeeCode = 'ABC123
ELSE
   INSERT person (FirstName, LastName, EmployeeCode) 
      VALUES ('Mike', "Hones', 'ABC123')

GraphQl spec discusses mutations but not what it looks like. The examples只涵盖INSERT场景。关于更新的唯一提及是它们 will/must/?连续执行。

原题-

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

我可以在传统的 SQL 方言和 ElasticSearch(通过查询更新)中使用几种方法来做到这一点。但我看不到它应该如何在 graphql 中指定或描述 - 或者如果它可能的话。

在规范和网络上有一些添加记录的示例,这些示例似乎需要看起来像 (like schema/type definitions) to be included in the document. The update examples often have field, argument, and variable names that dont match (like Author.Id and authorId) 的东西,或者是使用非 graphql 特定语言编写的,例如 Javascript(与“作者”相同的示例页面。)从终端客户端执行这两个阶段的操作似乎也不是正确的方法,因为只有目标数据存储才会知道哪个是正确的操作。

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

我问的有没有可能?如果可以,可以分享一个例子吗?

upsert-is-not-a-substitute-for-update

...那么它可以是一个宽松的解释...

createItem(如果你愿意,可以命名为upsertItem)突变解析器可以插入或更新(BE,解析器implementation/storage/DB相关决定)有或没有 strict/explicit 输入类型定义(创建需要,更新可选)

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

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

您可以限制字段使用(每个租户)或类型匹配(required/not 需要)在某些 验证 'layer' 内部解析器或中间件 中通过抛出错误(当输入与某些字段的特定 usage/tenant - f.e. return 'required error' 不匹配时,而类型定义中的所有字段都是可选的)。当内省查询被阻止(在生产中)时,这只是一个文档问题(不是自我描述)。

更新-示例

if the target entity to upsert is a Person with an ID, and First, and Last names, (ID and Last are required)

ID 这里不能要求...

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

对于创建upsertPerson( $input: UpsertPersonInput) {.. 具有创建所需的变量(通过验证规则)(First: "some", Last: "Name")

...ID 此处未知,已创建并 returned 作为结果

...没有提供 ID 然后假设 'creation mode'

对于更新:查询相同但当提供 input 变量和 ID prop 验证在 'update mode' 中工作(至少另一个变量 - input prop - 必需,f.e。Last ... 或其他附加验证规则)

... 虽然只提供了 input.ID 道具 > 抛出一些“不需要 'First' 在输入参数中传递”(任何字段)错误...因为它会在单独的更新突变及其输入类型。

答案是……你不知道。在 GraphQL 中没有用于指定或表达更新行为的句法或文法,除了解析器的笼统概念,您将必须完全创建自己的句法。对我来说,解析为不完整的查询语言。

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

当您必须在更新中提供所有字段时,没有自由,否则在使用 GraphQL 时将它们设置为 NULL。当你有一个 table 时,就没有自由,如下所示: TABLE1 ( ID NUMBER PK NOT NULL, FIRSTNAME VARCHAR2(20), LASTNAME VARCHAR2(20), COMPANY VARCHAR2(25), STATUS VARCHAR2(10) )

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

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