如何在单个突变中创建或更新实体



是否存在一个可接受的模式来创建或更新单个createOrUpdate突变中的项,其中用于创建和更新的字段不同?例如,这是我试图创建的类型和突变:

// The item shape
{
id: string
name: string
}
// the mutation pseudocode 
mutation {
saveItem(input: ItemCreate | ItemUpdate ){
if(input.id){
// update
}

if(!input.id){
// create 
}
}
}

似乎这些是正在使用的选项:

  1. 使用可为空的类型,然后运行类型检查来查找是否更新或创建
input UpdateOrCreate {
id: string // nullable
title: string // nullable
}
然后,您将有一个typeguard用于不同的场景,以检查是否更新或创建项,以及是否存在正确的属性组合。客户端的界面要好得多但这意味着你需要编写typeguard并将输入类型转换为更具体的类型
  1. 将不同的输入类型拆分为属性
input UpdateOrCreate {
updateItems: [ItemUpdateInput]
createItems: [ItemCreateInput]
}

当输入被验证时,这看起来像是图形化的方式,但是对于客户端来说,界面非常糟糕,因为我们告诉他们必须跟踪更新和创建

这有标准的方法吗?

我认为这两者都不是GraphQL方式™…至少现在还没有。目前有一个支持输入联合的建议,我认为它符合您正在寻找的模式。该功能目前尚未被接受,但可能很快就会被接受。

我们都在观望这些建议如何实现。在我进一步讨论之前,我必须补充一个警告,即没有真正的"标准方法"。这是我用了好几年的模式,也反映了其他人的观点,但每个人都有自己的风格。


My "hot take";

首先要明确,这样第三方就不必"猜测你的意思","知道你的实现细节";或者阅读你的文档来知道该怎么做。

一方面,"颠倒"的概念;或一个"CreateOrUpdate"在REST和orm中都是相对常见的,如果你传递了一个id,它就是一个更新,如果不是,它就是一个创建,所以我绝对可以看到你朝这个方向发展。另一方面,以下的想法:

  1. 你必须在每次调用时发送整个对象来更新吗?你一定要这么做吗?
  2. 如果没有,是否有些字段实际上是可选的,但仅在更新的情况下?如果是这样,你就进入了贫血突变的领域。哪些字段实际上是可选的,而哪些字段是&;only optional if…&;?
  3. 如果每个字段都需要所有的时间,这意味着什么发送id或不?实际上是createvsupdate,还是您的系统允许提供预生成的id ?如果您使用的是自动增量,那么答案很可能是"不"。如果您使用uid,那么答案可能是&;yes&;。如果我预生成一个ID并发送它,我应该得到NotFound错误返回,因为它是更新,还是应该创建,因为它是更新?

我所见过(和使用过)的最常见的方法是将其拆分为两个单独的突变,这使得事情更加明确。在update突变中,绝对需要id场。在create突变中,如果允许预先生成的id,则很容易通过具有可空的id来确定,如果存在,这就是我期望出现错误的地方。


话虽这么说,我也看到过类似你在第二个选项中得到的东西,但在处理一些批处理操作时使用。

input UpdateOrCreateLineItems {
orderId: ID!
lineItemsToCreate: [LineItemCreateInput!]
lineItemsToUpdate: [LineItemUpdateInput!]
lineItemsToDelete: [ID!]
}

再次警告:这是我基于我的需求的看法,你的意见和需求与我的不一样。

最新更新