GraphQL - Schema
GraphQL - Schema(模式)
Section titled “GraphQL - Schema(模式)”GraphQL Schema(模式)是任何 GraphQL API 的绝对核心。它作为客户端和服务器之间的强契约,精确定义了客户端可以请求什么数据、可以执行什么变更操作(Mutation),以及相关数据的结构。模式是使用 GraphQL Schema Definition Language (SDL) 定义的。
可以将模式视为 API 的蓝图或文档,但与传统文档不同的是,它是机器可读的,并由 GraphQL 服务器强制执行。
模式的核心组成部分
Section titled “模式的核心组成部分”- 类型(Types): 定义 API 中存在的不同种类的对象(Object)、标量(Scalar)、枚举(Enum)、接口(Interface)和联合(Union)。
- 字段(Fields): 类型中的属性,用于存放数据。每个字段都有特定的类型。
- 根操作类型(Root Operation Types): 定义操作入口点的特殊对象类型:
-
Query:定义可用的读取操作。
-
Mutation:定义可用的写入操作(创建、更新、删除)。
-
Subscription:定义可用的实时数据更新操作。
- 模式定义(可选但推荐): 明确声明哪些类型作为根操作类型(
query、mutation、subscription)。
模式定义语言(SDL)
Section titled “模式定义语言(SDL)”SDL 提供了一种简洁、人类可读的语法来定义模式。它是语言无关的,这意味着用 SDL 定义的模式可以由任何语言(如 JavaScript、Python、Java、C# 等)编写的 GraphQL 服务器实现。
常见的 SDL 元素:
type: 定义一个对象类型(Object type)。scalar: 定义一个自定义的原始类型(超出内置的 Int、Float、String、Boolean、ID)。enum: 定义一组预定义字符串值。input: 定义一个输入对象类型(Input Object type),主要用于 mutation 参数。interface: 定义一个契约,多个对象类型可以实现该契约。union: 定义一个类型,它可以是多个不同对象类型中的一个。!(感叹号): 表示字段或参数是 Non-Nullable(非空)的。[](方括号): 表示字段或参数是一个 List(列表/数组)。#或""": 用于注释或描述(描述会成为可内省模式的一部分)。
""" 表示一个教育机构 """type College { id: ID! # 学院的唯一标识符 name: String! location: String rating: Float students: [Student] # 与该学院关联的学生列表}
""" 表示注册入学的学生 """type Student { id: ID! firstName: String! lastName: String email: String! collegeId: ID! # 外键引用 college: College # 关联的 College 对象}
# 定义读取数据的入口点type Query { """ 获取所有学生的列表 """ students: [Student]
""" 根据学生的唯一 ID 获取单个学生 """ studentById(id: ID!): Student
""" 根据学院的唯一 ID 获取单个学院 """ collegeById(id: ID!): College}
# 用于创建新学生的输入类型input CreateStudentInput { firstName: String! lastName: String email: String! collegeId: ID!}
# 定义修改数据的入口点type Mutation { """ 创建一个新学生 """ createStudent(input: CreateStudentInput!): Student # 返回新创建的学生}
# 明确定义根操作类型(良好实践)schema { query: Query mutation: Mutation # subscription: Subscription # 如果有订阅则添加}将模式集成到 Apollo Server
Section titled “将模式集成到 Apollo Server”通常,你在设置过程中将模式定义(typeDefs)和相应的解析器(Resolvers)提供给 Apollo Server 实例。
方法 1:在代码中使用模式字符串(简单情况)
Section titled “方法 1:在代码中使用模式字符串(简单情况)”对于非常小的模式,你可以直接将 SDL 定义为模板字符串:
// server.jsimport { ApolloServer } from '@apollo/server';// ... 其他导入
const typeDefs = `#graphql type Query { greeting: String }`;
const resolvers = { Query: { greeting: () => 'Hello!' },};
const server = new ApolloServer({ typeDefs, // 直接传递模式字符串 resolvers,});
// ... 启动服务器方法 2:从 .graphql 文件加载(推荐)
Section titled “方法 2:从 .graphql 文件加载(推荐)”为了可维护性,最好将模式保存在单独的 .graphql 文件中。
- 创建一个包含 SDL 内容的
schema.graphql文件(如上面的示例所示)。 - 在服务器设置中加载文件内容:
// server.jsimport { ApolloServer } from '@apollo/server';import { readFileSync } from 'fs'; // Node.js 文件系统模块import path from 'path'; // Node.js path 模块import { fileURLToPath } from 'url'; // 处理 ES 模块路径// ... 其他导入
// 加载解析器(假设 resolvers.js 存在)import resolvers from './resolvers.js';
// 在 ES 模块中获取目录名const __filename = fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);
// 从文件加载模式const typeDefs = readFileSync(path.join(__dirname, 'schema.graphql'), { encoding: 'utf-8',});
const server = new ApolloServer({ typeDefs, // 传递已加载的模式字符串 resolvers,});
// ... 启动服务器(注意:如果使用 CommonJS 的 require 而非 ES 模块的 import,文件加载方式可能略有不同。)
内省(Introspection)
Section titled “内省(Introspection)”模式实现了一个强大的功能,即内省(Introspection)。GraphQL 服务器会暴露一组特殊字段(前缀为 __,例如 __schema、__type),允许客户端查询模式本身。Apollo Sandbox、GraphiQL 和 Apollo Client DevTools 等工具利用内省提供了自动补全、文档浏览和模式可视化等功能,无需单独的文档接口(endpoint)。
内省默认在开发环境中启用,出于安全考虑,通常在生产环境中禁用,不过这是可配置的。
Schema-First 与 Code-First
Section titled “Schema-First 与 Code-First”这里展示的方法是先使用 SDL 定义模式,然后编写相应的解析器与之匹配,这称为 schema-first(模式优先)开发。由于 SDL 的清晰性和语言无关性,这种方法非常流行。
另一种方法是 code-first(代码优先),在这种方法中,你使用编程语言结构(例如在 TypeScript 中使用类或装饰器,配合 TypeGraphQL 或 NestJS GraphQL 等库)定义类型和解析器,然后 SDL 模式会从你的代码自动生成。这两种方法都有效,选择哪种通常取决于团队偏好和项目需求。