Graphql 有嵌套突变会有多糟糕?

Graphql 有嵌套突变会有多糟糕?,graphql,Graphql,我知道这会被视为一种反模式,但确切的原因是什么 mutation { createUser(name: "john doe") { addToTeam(teamID: "123") { name, id }, id } } 这不是比两个HTTP调用更方便吗 mutation { createUser(name: "john doe") { id, # we store the ID } } mutation { a

我知道这会被视为一种反模式,但确切的原因是什么

mutation {
  createUser(name: "john doe") {
    addToTeam(teamID: "123") {
      name,
      id
    },

    id
  }
}
这不是比两个HTTP调用更方便吗

mutation {
  createUser(name: "john doe") {
    id, # we store the ID
  }
}

mutation {
  addToTeam(userID: id, teamID: "123") {
    name,
    id,
  }
}

如果
团队
用户
之间存在关系,则可以公开此API:

创建用户,与现有团队相关

mutation {
  createUser(name: "john doe", teamId: "team-id") {
    id
    team {
      id
    }
  }
}
mutation {
  createUser(name: "john doe", team: {name: "New team"}) {    
    id
    team {
      id
    }
  }
}
创建新用户和新团队

mutation {
  createUser(name: "john doe", teamId: "team-id") {
    id
    team {
      id
    }
  }
}
mutation {
  createUser(name: "john doe", team: {name: "New team"}) {    
    id
    team {
      id
    }
  }
}

这正是GraphTool API处理此问题的方式,如中所示。您可以在中找到另一个示例。

这是反模式的原因有两个:

首先,这里有两个原子操作,每个操作可能涉及一些与身份验证、验证相关的额外逻辑,并产生不同的错误。因此,将它们混合在一起可能会导致一些额外的复杂性

例如,假设一个团队只能有10人,并且已经达到了最大人数。是否应该组合操作全部失败?我们是否只添加用户,而不将其添加到团队中?反应会是什么样子

其次,以这种方式集中两个操作可能会暴露应用程序逻辑。人们可能会尝试使用这种突变来执行“当X发生时,Y也应该发生”。例如,将新行添加到发票时,总计应更新。这实际上应该发生在一个变种addLineToInvoice上,并让逻辑驻留在服务器上


在某种程度上,API的命令部分以流程(或操作)为中心比以数据为中心更好。如果您的API调用集中在数据操作上,那么您就有可能用应该存在于服务器中的业务逻辑加载客户机。您可能还失去了很多好东西,如中间件(它非常适合交叉关注点,如权限和日志记录)。

为什么不在
createUser()中添加可选的
teamID
,要在一个HTTP请求中使用更传统的变体完成这一切?是的,如果每次都想将用户添加到团队中,它实际上会起作用,但如果不是这样,是否需要在服务器上创建一个额外的变体:
createuserandddtoteam
?“如果您每次都想将用户添加到团队中,那么它实际上是可行的“--否。可选的
teamID
是可选的。使用
字符串意味着您可以传入
null
以表示您不想将用户添加到团队中。哦,是的,我没有考虑过该选项。如何将此变异的参数传递给嵌套类型?返回字段
team{id}
是如何解析的?我正在尝试做一个类似的突变,但GraphQL说它需要一个根参数: