GraphQL 是一种由 Facebook 开发的数据查询和操作语言,旨在提高 API 的速度和灵活性。它允许客户端指定它需要什么数据,而无需关心后端如何组织和查询数据。然而,GraphQL 查询深嵌套很容易导致性能问题和复杂性,因此本文将介绍一些可用的处理方式。
问题与挑战
GraphQL 查询通常涉及多个字段和关联。例如,下面是一个查询文章及其作者的示例:
-- -------------------- ---- ------- - ----------- ---- - ----- ---- ------ - ---- ----- - - -
在查询处理过程中,GraphQL 服务器需要执行以下操作:
- 查询文章信息和相关联的用户。
- 将查询结果转换为 JSON 对象。
- 将结果发送回客户端。
书写 GraphQL 查询可能很简单直接,但是在服务器端构建出一个好的查询执行计划,则要使用最少的资源生成最优的结果,是一个复杂的任务。
与之相对的是 Netflix 就 GraphQL 的使用体验的建言。他们认为对于客户端来说,需要为其返回的数据增加灵活性,而在服务端则需要对于查询的语句,减少代码的业务复杂度以及保持系统稳定性。
避免嵌套查询的方法
下面将介绍一些用于避免嵌套查询的策略。
1. Flatten 数据模型
通常情况下,GraphQL 的实体模型映射到数据模型时,具有多个级别的嵌套。例如,在博客系统中,一个帖子具有标题、内容和作者,而作者又具有名字和电子邮件。如果我们想查询一篇文章以及它的作者,查询可能如下所示:
-- -------------------- ---- ------- ----- - -------- ---- - ----- ------- ------ - ---- ----- - - -
在 API 中处理此查询会涉及嵌套数据结构。如果层数较多,这将导致查询响应变慢。为了解决这个问题,我们可以尽量将嵌套的数据扁平化。在这个例子中,我们可以将文章和作者属性存储为单独的对象,并一起返回。
2. 使用 GraphQL Fragments
GraphQL Fragments 提供了一种重复使用查询部分的方法。通过将查询拆分为多个部分,然后将其组合在一起,客户端可以根据需要使用特定的函数,并且服务器可以将结果与预定义的查询结果比较。例如,在上述博客示例中,我们可以定义片段来表示文章以及文章的作者:
-- -------------------- ---- ------- -------- ---------- -- ---- - ----- ------- ------ - ---- ----- - - ----- - -------- ---- - ------------- - -
在这种情况下,客户端将完整的查询拆分为两个不同的部分。在实际的 GraphQL 应用程序中,我们可以定义多个 Fragment,以更好地组织查询和避免查询嵌套的问题。
3. Batch 查询
发出多个查询是调用 GraphQL API 新手的常见错误。在复杂的查询中,这可能会导致服务器的巨大开销并且占用内存资源。相反,我们可以使用 Batch 查询来批量处理网络请求。Batch 查询允许客户端将多个查询打包并发送到服务器,从而减少网络负载并优化查询响应时间。
GraphQL API 让服务器对于诸如 Facebook的 Feed 数据那样的复杂对象/多次行动链请求时加入 batch-support 以优化服务器性能。
4. Use Pagination
当我们需要在很大的数据集中进行查询时,使用分页是一个很好的选择。通过将查询分解成多个页面,而不是一次性加载整个集合,我们可以显著减少每个请求的响应时间。只需要注意避免 skip 和 limit 这样的分页方式,因为其内存上分担不均等可能会导致资源瓶颈的情况。
示例代码
下面是 Node.js 中的一些 GraphQL 解析器函数示例。这些函数演示了如何使用 MongoDB 数据库存储多个级别的数据,然后使用 GraphQL 触发器查询它们:
-- -------------------- ---- ------- ----- --------- - - ------ - ------ ----- -- -- ----- ---------------- ------ ----- -- -- ----- ---------------- --------- ----- -- -- ----- ------------------ -- ----- - ------ ----- -------- ----- -- ----- --------------- ------- ---------- -- -- ----- - ------- ----- -------- ----- -- ----- ------------------ ---- ------------- --- --------- ----- -------- ----- -- ----- ------------------ ----- ---------- -- -- -------- - ----- ----- -------- ----- -- ----- ------------------ ---- ----------- --- ------- ----- -------- ----- -- ----- ------------------ ---- ------------- -- - --
这些函数执行了如下的 GraphQL 查询:
-- -------------------- ---- ------- - ----- - --- ---- ----- ----- - --- ----- ------- ------ - --- ---- ----- - -------- - --- ---- ---- - --- ----- - ------ - --- ---- ----- - - - - -
由于这是一个多层次的查询,需要大量的嵌套。然而,我们可以处理嵌套数据结构,使其扁平和易于分析。GraphQL 能够处理所有这些查询和响应转换,但在这个查询会面临性能和内存问题,应该采用上述的几种建议。
总结
使用 GraphQL 可以让我们更灵活的请求数据,不过也可能导致性能问题和复杂性。在设计 GraphQL 架构时,我们应该尽量将数据扁平化,使用 Fragment 和 Batch 查询来避免嵌套查询的问题。通过合理的处理,可以使 GraphQL 架构具有良好的性能并保持简洁易懂的代码模型。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64ffd31295b1f8cacde1b5e5