graphql中嵌套突变的良好CRUD动词语义是什么?

graphql中嵌套突变的良好CRUD动词语义是什么?,graphql,graphql-js,Graphql,Graphql Js,graphql中的嵌套对象似乎继承了父对象的动词语义。这导致了关于什么的问题 CRUD语义应该用于嵌套突变 例如,如果我希望创建一个对象,并在更新该现有对象时将其连接到现有关联对象,则父对象语义为create,嵌套对象语义为update。然而,GraphQL不明确允许在单个原子突变(AFAICT)中使用混合动词 下面是一个真值表,它显示了当嵌套对象位于数据库中或变异中,或两者同时存在时的一些问题: | in mutation| in database| action on create | ac

graphql中的嵌套对象似乎继承了父对象的动词语义。这导致了关于什么的问题 CRUD语义应该用于嵌套突变


例如,如果我希望创建一个对象,并在更新该现有对象时将其连接到现有关联对象,则父对象语义为create,嵌套对象语义为update。然而,GraphQL不明确允许在单个原子突变(AFAICT)中使用混合动词

下面是一个真值表,它显示了当嵌套对象位于数据库中或变异中,或两者同时存在时的一些问题:

| in mutation| in database| action on create | action on update | Notes 
|------------|------------|------------------|------------------|-------
| False      | False      | create if rule   | create if rule   | a rule might be cardinality === 1.
| False      | True       | None             | None             | no harm no foul
| True       | False      | Create           | Create? Err?     | better ask for ID back or will have to query edges later
| True       | True       | Update?  Err?    | Update           | what if the mutation doesn't contain the ID?
请注意,“更新时的操作”需要在变异中包含一个ID,否则它将根据业务规则转变为创建或错误

处理嵌套对象的一种方法是,如果包含ID,则将其视为更新。当发生编码错误时,这将导致意外创建嵌套对象。这也是难看的语义

第二种方法是将父对象的谓词视为嵌套对象的同一谓词,除非在“创建”上,如果嵌套对象的ID存在,则嵌套对象将被视为更新

第三种选择是需要多个突变,以使用下一个突变的返回ID来处理嵌套对象。这是3次往返,它破坏了单个突变的自然原子性, 这将导致一个巨大的一致性问题

创建和更新嵌套对象的最佳动词语义是什么

下面是一个明确的例子。答案将显示上表中模棱两可的场景的变化

O1<----hasa---->O2

O1 {
  id: "1234",
  descr: "Object1",
  someAttr: "foo"
}

O2 {
  id: "5678",
  descr:  "Object2",
  someOtherAttr: "bar"
}

hasa {
  id1: "1234",
  id2: "5678",
  type: "hasa"
  edgeAttr: "someRelationAttr"
}

我想知道当O2已经在数据库中时,O1Create突变的好选择是什么。我还想知道当O2不在数据库中时,O1更新的好选择是什么。

“但是GraphQL不明确允许在单个原子突变中使用混合动词”——GraphQL实际上没有动词,除了您自己定义的以外。GraphQL是一个具有额外功能的RPC框架。
O1Create
的功能完全取决于您,可能会受到您选择的服务器端GraphQL解析器/解析器支持的任何限制。“它也是丑陋的语义”--::耸耸肩::如果您考虑如何在SQL事务中进行插入或替换,它基本上是
INSERT或REPLACE
。也许“丑陋的语义”是一个错误的术语。ID的存在或缺乏最好称为丑陋语法。实际上,我对INSERT或REPLACE没什么意见,它是幂等的,这在大多数情况下对于分布式系统是非常理想的。(除了创建用户或与安全性相关的东西……)至于动词,这实际上是GraphQL的一个问题。动词有两类,mutate和query。这里的问题是,不管涉及的对象数量有多大,每个变种只会得到一个动词。如果我有比插入或替换更复杂的事情,我就倒霉了。动词的arg?
mutate
query
,IMHO是有限的标记,仅此而已。规范在它们周围放置了一些规则(例如,
query
不能修改数据),但仅此而已。同样,GraphQL是一个RPC框架,在很大程度上,您可以在为远程使用而公开的过程中做任何您想做的事情。您的问题虽然有效,但并非GraphQL所独有。在其他任何地方执行相同类型的操作都会遇到同样的问题。例如,使用一个C函数、一个REST调用或一个gRPC调用,实现
O1Create
。我想要什么都行,但我对人们实际使用的模式很好奇。没有约束的编码会导致奇怪的结果。“然而GraphQL不允许在单个原子突变中显式地使用混合动词”——GraphQL除了定义自己之外,实际上没有动词。GraphQL是一个具有额外功能的RPC框架。
O1Create
的功能完全取决于您,可能会受到您选择的服务器端GraphQL解析器/解析器支持的任何限制。“它也是丑陋的语义”--::耸耸肩::如果您考虑如何在SQL事务中进行插入或替换,它基本上是
INSERT或REPLACE
。也许“丑陋的语义”是一个错误的术语。ID的存在或缺乏最好称为丑陋语法。实际上,我对INSERT或REPLACE没什么意见,它是幂等的,这在大多数情况下对于分布式系统是非常理想的。(除了创建用户或与安全性相关的东西……)至于动词,这实际上是GraphQL的一个问题。动词有两类,mutate和query。这里的问题是,不管涉及的对象数量有多大,每个变种只会得到一个动词。如果我有比插入或替换更复杂的事情,我就倒霉了。动词的arg?
mutate
query
,IMHO是有限的标记,仅此而已。规范在它们周围放置了一些规则(例如,
query
不能修改数据),但仅此而已。同样,GraphQL是一个RPC框架,在很大程度上,您可以在为远程使用而公开的过程中做任何您想做的事情。您的问题虽然有效,但并非GraphQL所独有。在其他任何地方执行相同类型的操作都会遇到同样的问题。例如,使用一个C函数、一个REST调用或一个gRPC调用,实现
O1Create
。我想要什么都行,但我对人们实际使用的模式很好奇。没有约束的编码会导致奇怪的结果。
mutation { O1Create(
  descr: "Object1",
  someAttr: "foo",
  hasa {
    edgeAttr: "someRelationAttr",
    O2 { 
      descr: "Object2",
      someOtherAttr: "bar"
    } 
  }   
)}