【问题标题】:GraphQL: Many small mutations, or one bulk mutation?GraphQL:许多小的突变,还是一个大的突变?
【发布时间】:2017-10-28 01:17:21
【问题描述】:

假设我是一名用户,我正在某个任意应用程序上编辑我的个人资料。该应用程序让我进行了一系列更改,完成后,我点击“保存”,我的个人资料就会更新。

在 GraphQL 中处理此类大型更新的推荐最佳做法是什么?在我看来,有几个选择:

A) 许多小的突变。如果用户更改了 5 项内容(即姓名、电子邮件、用户名、图像、简历),则客户端可以向服务器触发 5 次更改。

优点:更小、更孤立的操作。

缺点:这不是违背了 GraphQL 中“往返服务器”的目的,因为它需要... 5?

B) 许多小的突变,称为服务器端。与其从客户端调用 5 个变更(需要 5 次往返),不如将一个数据 blob 发布到服务器并拥有一个解析它的函数,并对它找到的数据运行单个变更。

优点:往返一次

缺点:我们必须在应用程序中添加另一个层来处理这个问题。随着时间的推移,新功能会变得混乱、难以测试且难以维护。

C) 一个大突变。用户通过单个突变将数据 blob 发送到服务器,这会将新数据批量设置在文档上,而不是在每个字段上运行单独的突变。

优点:DX;往返一次。

缺点:由于字段是作为参数传入的,这会使应用程序受到攻击。恶意用户可以尝试传入任意字段,设置不应更改的字段(即isAdmin 字段)等。突变必须聪明地知道允许更新哪些字段,并拒绝/忽略其余的。


我在网上找不到太多关于哪种方式是在 GraphQL 中做这种事情的“正确方式”。希望在这里找到一些答案/反馈。谢谢!

【问题讨论】:

  • 往返服务器的真正目的是查询,而不是突变。
  • 我认为你想多了。方法 1 和 3 都是解决此问题的正确方法,具体取决于您的需要。我会选择 3,这在大多数情况下可能是最稳健的方式。

标签: graphql relay apollo


【解决方案1】:

A) 许多小的突变。如果用户更改了 5 项内容(即姓名、电子邮件、用户名、图像、简历),则客户端可以向服务器触发 5 次更改。

您可以在一个请求中执行多个变更。无需多次调用服务器。

这是一个例子:

mutation {
  setUserName(name: "new_name") { ok }
  setUserEmail(email: "new_email") { ok }
}

B) 许多小的突变,称为服务器端。与其从客户端调用 5 个变更(需要 5 次往返),不如将一个数据 blob 发布到服务器并拥有一个解析它的函数,并对它找到的数据运行单个变更。

这正是 GraphQL 在您更改多个字段或一次执行多个查询时为您做的事情。

C) 一个大突变。用户通过单个突变将数据 blob 发送到服务器,该突变将新数据批量设置在文档上,而不是在每个字段上运行单独的突变。

即使您使用多个字段,您仍然可以批量设置数据。
这将要求您将请求传递给中间件,而不是直接更新数据库,该中间件将在执行所有突变解析器后构建并执行单个查询。

缺点:由于字段是作为参数传入的,这会使应用程序受到攻击。恶意用户可以尝试传入任意字段,设置不应更改的字段(即 isAdmin 字段)等。突变必须聪明地知道允许更新哪些字段,并拒绝/忽略其余字段.

您不应使用任意变量,而应将所有允许的属性作为参数列出。

【讨论】:

    【解决方案2】:

    我会选择第三种解决方案,一个大突变。我不确定我是否理解您关于恶意用户传递任意字段的观点:他们将无法传递未在您的架构中定义的字段。

    至于服务器端逻辑,无论如何您都必须进行智能检查:您永远不能信任客户端!

    【讨论】:

    • 谢谢!我肯定是在考虑它的安全方面。我没有意识到您不能将任意值传递给突变来尝试欺骗它,您只能提供架构中指定的确切字段,并且它们必须是预期的类型。因此,这意味着您可以从单个突变中获得的工作越多越好。这是更大、更通用的突变!
    猜你喜欢
    • 2022-01-13
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2019-01-23
    • 2021-03-09
    • 2016-01-13
    • 2019-11-27
    相关资源
    最近更新 更多