← [ BACK_TO_NOTES ]

GraphQL Schema

GraphQL Schema 是客户端与服务端共享的强类型 API 契约,规定可查询的类型、字段、参数、根操作与可空性边界。

#concept #growing #api #graphql

GraphQL Schema

一句话定义

GraphQL Schema 是 API 的类型契约:它声明“客户端允许问什么、参数长什么样、服务端承诺返回什么形状”。

它描述 API,而不是数据库表结构。

为什么需要 Schema

REST 常把契约分散在 URL、HTTP 方法、DTO 和文档里;GraphQL 把可查询能力集中进一个类型系统,因此客户端可以在发送请求前知道字段是否存在、参数是否合法、返回值是否可能为空。

type User {
  id: ID!
  name: String!
  age: Int
}

type Query {
  user(id: ID!): User
}

这里表达了几个稳定事实:

  • User.id、User.name 必须有值;
  • age 可以为空;
  • 客户端可以从根 Query 查询 user;
  • user 必须接收一个非空 ID;
  • 查询结果本身可能找不到,因此 User 没有 !。

Schema 怎样成为前后端接口合同

在 REST 团队中,前端常通过 OpenAPI / Swagger / Apifox 等文档知道:

URL
HTTP method
request body
response DTO

GraphQL 中,这一层的核心真值就是 Schema 本身。

最常见的声明方式是 SDL(Schema Definition Language):

type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
}

也可以采用 code-first:先用某种语言的类型/构造器定义 Schema,再由框架生成等价的 GraphQL Schema。无论来源是哪种,真正提供给客户端验证和执行的仍是一棵 GraphQL 类型系统。

GraphQL 还定义了 introspection。客户端或工具可以查询 Schema 自己,得到:

有哪些 Query / Mutation / Subscription
有哪些 Object / Enum / Union / Interface
字段叫什么、是什么类型
参数是什么类型
哪些位置允许 null

因此常见团队工作流是:

Backend Schema
   ↓ publish / introspection / schema registry
GraphQL tooling
   ├─ 自动文档
   ├─ IDE 自动补全
   ├─ operation validation
   └─ TypeScript codegen
          ↓
Frontend Query / Mutation

所以 GraphQL 的接口文档不只是给人阅读的说明书,而可以成为 机器可读取、可校验、可生成代码的 executable contract。

实际生产环境是否开放公网 introspection 是部署与安全策略问题;即使关闭公开 introspection,团队仍可以通过构建产物、Schema 文件或 registry 向前端发布同一份合同。

核心模型

Scalar

GraphQL 内置常见标量:Int、Float、String、Boolean、ID。

标量是查询树的叶子;客户端最终选择的普通字段通常落到标量。

Object

type Diagnosis {
  id: ID!
  summary: String!
  author: User!
}

对象字段可以继续指向另一个对象,因此查询可以沿关系展开。

List 与 Nullability

[Diagnosis!]!

从里向外读:

  • Diagnosis!:列表元素不能是 null;
  • [...]!:列表本身不能是 null。

不要把 ! 理解成 TypeScript 的非空断言;它是服务端公开契约的一部分。

Root Types

type Query { ... }
type Mutation { ... }
type Subscription { ... }

它们定义客户端进入整个数据图的入口:读取、写入与实时订阅。

Schema 的验证边界

Schema 很擅长验证:

字段是否存在
参数是否缺失
String / Int / Float 等基础类型是否匹配
nullability 是否满足
输入对象 shape 是否符合声明

但默认:

email: String!
age: Int!

并不能自动证明:

email 是合法邮箱格式
age >= 18
score 在 0..100

这些通常还需要自定义 Scalar / Directive,或更常见地在 application boundary 使用 Zod 等 runtime validation,再由 Service / Domain 处理业务规则。

因此:

GraphQL Type Validation
≠ 完整 Runtime Validation
≠ Business Validation
≠ Database Constraint

Schema 不负责什么

Schema 能证明“请求形状合法”,但不能证明:

  • 当前用户有权限读取该字段;
  • 数据库一定存在对应记录;
  • resolver 不会报错;
  • 返回内容符合业务事实;
  • 查询成本一定合理;
  • String! 一定符合邮箱、URL 等业务格式;
  • Int! 一定满足业务范围约束。

这些属于 runtime validation、resolver、授权、业务规则、数据库约束和执行治理。

最重要的心智模型

GraphQL Schema
      ↓ 约束
客户端 Operation
      ↓ 执行
Resolver
      ↓
Service / Repository / Database

Schema 是公开边界,Resolver 才把这个边界连接到真实业务实现。

常见误解

  • Schema = 数据库 schema:不是。GraphQL Schema 面向 API,可以组合、隐藏或重塑数据库数据。
  • Schema = 一份手写接口说明文档:不只是。它是 GraphQL Server 真正用于验证和执行 operation 的机器合同。
  • 有类型就没有运行时错误:不是。类型只能覆盖契约中的一部分运行时问题。
  • String! 就能验证 Email:不能,除非额外定义语义验证机制。
  • 对象之间有关系就一定 JOIN:不是。如何取数由 resolver 决定,也正因此可能产生 N+1。
创建于 2025/1/1 更新于 2026/9/15
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本