GraphQL 架构设计:如何避免查询嵌套问题

GraphQL 是一种由 Facebook 开发的数据查询和操作语言,旨在提高 API 的速度和灵活性。它允许客户端指定它需要什么数据,而无需关心后端如何组织和查询数据。然而,GraphQL 查询深嵌套很容易导致性能问题和复杂性,因此本文将介绍一些可用的处理方式。

问题与挑战

GraphQL 查询通常涉及多个字段和关联。例如,下面是一个查询文章及其作者的示例:

-
  ----------- ---- -
    -----
    ----
    ------ -
      ----
      -----
    -
  -
-

在查询处理过程中,GraphQL 服务器需要执行以下操作:

  1. 查询文章信息和相关联的用户。
  2. 将查询结果转换为 JSON 对象。
  3. 将结果发送回客户端。

书写 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


猜你喜欢

  • 应用 ECMAScript 2019 的 Array.sort 方法实现数组排序功能

    使用 ECMAScript 2019 的 Array.sort 方法实现数组排序功能 在前端开发过程中,数组排序是非常常见和基本的操作之一。ECMAScript 2019 新增了一些功能强大的方法,使...

    1 年前
  • 如何在 Cypress 中自动填充 JWT Token?

    在前端开发中,我们经常需要进行自动化测试,而 Cypress 是一种优秀的自动化测试工具,它提供了强大的 API 和易于使用的界面,同时还拥有一些内置的功能,例如自动化填充 JWT Token。

    1 年前
  • 在 Angular 中解决 “Expected role attribute of value searchbox,but saw xyz” 错误

    在使用 Angular 构建 Web 应用程序的过程中,开发者可能会遇到一个错误,即“Expected role attribute of value searchbox,but saw xyz”(期...

    1 年前
  • ECMAScript 2021 (ES12) 中的 RegExp 的新特性详解

    ECMAScript 2021 (ES12) 中的 RegExp 的新特性详解 正则表达式(RegExp)是前端开发中常用的工具,用于匹配和替换文本中的模式。在 ECMAScript 2021 标准中...

    1 年前
  • LESS 中使用嵌套规则和父元素选择器

    LESS(Leaner Style Sheets)是一种 CSS 预处理器语言,它通过提供类似编程语言中循环、函数等功能,帮助我们更高效、更可维护地编写样式文件。其中,LESS 中的嵌套规则和父元素选...

    1 年前
  • Deno 中的事件驱动编程模型介绍

    Deno 是一款现代化的服务器端 JavaScript 和 TypeScript 运行时,其对事件驱动编程模型进行了深度改造,更加符合现代化编程的需求。本文将介绍 Deno 中的事件驱动编程模型,并给...

    1 年前
  • SASS 语法中常见错误及排错方法

    在前端开发中,SASS 是一种非常流行的 CSS 预处理器,它可以帮助我们更快、更方便地编写 CSS。然而,由于 SASS 语法的复杂性以及开发者对其不熟悉,常常在编写 SASS 代码时出现错误。

    1 年前
  • Node.js 中使用 MySQL 数据库的最佳实践

    MySQL 是当前最流行的关系型数据库之一,在 Node.js 应用中使用 MySQL 数据库能够为我们提供强大的数据持久化支持。但是,在使用 MySQL 数据库的过程中,我们也需要遵循一定的最佳实践...

    1 年前
  • Tailwind 新手入门指南:如何使用 Tailwind 开发 Web 应用

    前言 Tailwind 是一个基础 UI 库,它提供了一系列 CSS 类,可以帮助开发者快速构建漂亮的用户界面。Tailwind 的特点是可定制性强,开发者可以根据自己的需求进行灵活的设置,并且大大降...

    1 年前
  • Web 组件:解决 Web 前端工程师痛点的技术

    Web 前端开发已经成为了当下最热门的技能之一。随着互联网技术的飞速发展,Web 应用的功能和复杂度也越来越高。这对于前端工程师来说,意味着需要不断地创新和学习新的技术。

    1 年前
  • PM2 如何进行 Node.js 应用的自动迁移

    在进行应用迭代升级、部署新环境等操作时,如何迁移原有的 Node.js 应用非常重要。过去,我们可能需要手动备份、恢复数据,以及重新安装依赖包等操作。但是,现在的自动化工具能够极大地简化这一流程,例如...

    1 年前
  • ECMAScript 2017 (ES8) 之正则表达式的总结

    正则表达式是一种用于匹配文本模式的特殊文本序列。在前端开发中,正则表达式也经常被用于数据验证和文本处理等方面。在 ECMAScript 2017 中增加了一些新特性,让正则表达式的应用更加灵活和方便。

    1 年前
  • 一文读懂 ES6 中的模板字面量

    ES6(ECMAScript 6)是 JavaScript 的一个版本,带来了很多新特性。其中,模板字面量(Template literals)是一个非常有用的特性,它可以让字符串的拼接和变量的引用变...

    1 年前
  • Babel 不能编译 import、export 语法是什么问题,如何解决?

    在 JavaScript 的新标准 ES6 中,我们可以使用 import 和 export 语法来引入和导出模块,但是在使用 Babel 编译器编译代码时,却发现这些语法不能被正确编译,导致代码无法...

    1 年前
  • 如何使用 Webpack 对 jQuery UI 进行打包?

    前言 在前端开发中,我们经常需要使用第三方库来提高开发效率,其中 jQuery UI 是一个非常方便的 UI 库。但是,由于 jQuery UI 包含了许多组件和文件,直接引用可能会导致页面加载速度变...

    1 年前
  • React Router v4 完全指南:路由、导航等

    React Router 是 React 应用中最受欢迎的路由库之一。React Router V4 是目前最新的版本,带来了一些重大变化。相较以前,React Router V4 在 API 以及用...

    1 年前
  • 前端单元测试框架 - 基于 Mocha, Chai, Sinon 的测试工具详解

    前端单元测试框架 - 基于 Mocha, Chai, Sinon 的测试工具详解 随着 web 应用程序的复杂度不断增加,前端单元测试变得越来越重要。前端单元测试的主要目的是确保代码的正确性和稳定性。

    1 年前
  • PWA 性能调优大杀器:Chrome DevTools

    PWA(Progressive Web App)是一种新兴的技术,它可以模拟原生应用程序的体验,而不需要用户去下载安装应用程序。但是,如果你没有进行 PWA 性能调优,你的应用程序可能会运行得很慢。

    1 年前
  • 使用 S3 构建 Serverless 架构的数据处理流程

    随着云计算技术的不断发展,Serverless 架构也越来越受到开发者的青睐。在 Serverless 架构中,开发者不需要管理服务器的运维和扩展,只需要编写函数并将其上传到云平台,就能够快速构建各种...

    1 年前
  • 解决 Material Design 中 CardView 阴影异常的问题

    在 Android 开发中,CardView 是 Material Design 中经常使用的 UI 元素之一,它以卡片的形式展现数据,常常被用来作为列表项或者整个界面的背景。

    1 年前

相关推荐

    暂无文章