graphql-schema
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGraphQL Schema Design Guide
GraphQL Schema设计指南
This guide covers best practices for designing GraphQL schemas that are intuitive, performant, and maintainable. Schema design is primarily a server-side concern that directly impacts API usability.
本指南涵盖了设计直观、高性能且易于维护的GraphQL Schema的最佳实践。Schema设计主要是服务端层面的工作,直接影响API的易用性。
Schema Design Principles
Schema设计原则
1. Design for Client Needs
1. 以客户端需求为设计核心
- Think about what queries clients will write
- Organize types around use cases, not database tables
- Expose capabilities, not implementation details
- 思考客户端会编写哪些查询
- 围绕用例组织类型,而非数据库表
- 暴露功能能力,而非实现细节
2. Be Explicit
2. 保持明确性
- Use clear, descriptive names
- Make nullability intentional
- Document with descriptions
- 使用清晰、描述性的名称
- 有意设计可空性
- 为类型和字段添加描述文档
3. Design for Evolution
3. 为演进性设计
- Plan for backwards compatibility
- Use deprecation before removal
- Avoid breaking changes
- 规划向后兼容性
- 在移除前先标记废弃
- 避免破坏性变更
Quick Reference
快速参考
Type Definition Syntax
类型定义语法
graphql
"""
A user in the system.
"""
type User {
id: ID!
email: String!
name: String
posts(first: Int = 10, after: String): PostConnection!
createdAt: DateTime!
}graphql
"""
系统中的用户。
"""
type User {
id: ID!
email: String!
name: String
posts(first: Int = 10, after: String): PostConnection!
createdAt: DateTime!
}Nullability Rules
可空性规则
| Pattern | Meaning |
|---|---|
| String | Nullable - may be null |
| String! | Non-null - always has value |
| [String] | Nullable list, nullable items |
| [String!] | Nullable list, non-null items |
| [String]! | Non-null list, nullable items |
| [String!]! | Non-null list, non-null items |
Best Practice: Use [Type!]! for lists - empty list over null, no null items.
| 模式 | 含义 |
|---|---|
| String | 可空 - 可能为null |
| String! | 非空 - 始终有值 |
| [String] | 可空列表,列表项可空 |
| [String!] | 可空列表,列表项非空 |
| [String]! | 非空列表,列表项可空 |
| [String!]! | 非空列表,列表项非空 |
最佳实践: 对列表使用**[Type!]!**模式 - 返回空列表而非null,且列表项不可为空。
Input vs Output Types
输入类型 vs 输出类型
graphql
undefinedgraphql
undefinedOutput type - what clients receive
输出类型 - 客户端接收的数据类型
type User {
id: ID!
email: String!
createdAt: DateTime!
}
type User {
id: ID!
email: String!
createdAt: DateTime!
}
Input type - what clients send
输入类型 - 客户端发送的数据类型
input CreateUserInput {
email: String!
name: String
}
input CreateUserInput {
email: String!
name: String
}
Mutation using input type
使用输入类型的Mutation
type Mutation {
createUser(input: CreateUserInput!): User!
}
undefinedtype Mutation {
createUser(input: CreateUserInput!): User!
}
undefinedInterface Pattern
接口模式
graphql
interface Node {
id: ID!
}
type User implements Node {
id: ID!
email: String!
}
type Post implements Node {
id: ID!
title: String!
}graphql
interface Node {
id: ID!
}
type User implements Node {
id: ID!
email: String!
}
type Post implements Node {
id: ID!
title: String!
}Union Pattern
联合类型模式
graphql
union SearchResult = User | Post | Comment
type Query {
search(query: String!): [SearchResult!]!
}graphql
union SearchResult = User | Post | Comment
type Query {
search(query: String!): [SearchResult!]!
}Reference Files
参考文档
Detailed documentation for specific topics:
- Types - Type design patterns, interfaces, unions, and custom scalars
- Naming - Naming conventions for types, fields, and arguments
- Pagination - Connection pattern and cursor-based pagination
- Errors - Error modeling and result types
- Security - Security best practices for schema design
特定主题的详细文档:
- Types - 类型设计模式、接口、联合类型和自定义标量
- Naming - 类型、字段和参数的命名规范
- Pagination - 连接模式和基于游标分页
- Errors - 错误建模和结果类型
- Security - Schema设计的安全最佳实践
Key Rules
关键规则
Type Design
类型设计
- Define types based on domain concepts, not data storage
- Use interfaces for shared fields across types
- Use unions for mutually exclusive types
- Keep types focused (single responsibility)
- Avoid deep nesting - flatten when possible
- 基于领域概念定义类型,而非数据存储结构
- 对跨类型的共享字段使用接口
- 对互斥类型使用联合类型
- 保持类型聚焦(单一职责)
- 避免深层嵌套 - 尽可能扁平化
Field Design
字段设计
- Fields should be named from client's perspective
- Return the most specific type possible
- Make expensive fields explicit (consider arguments)
- Use arguments for filtering, sorting, pagination
- 从客户端视角命名字段
- 返回最具体的类型
- 明确标记开销大的字段(考虑添加参数)
- 使用参数进行过滤、排序和分页
Mutation Design
Mutation设计
- Use single input argument pattern:
mutation(input: InputType!) - Return affected objects in mutation responses
- Model mutations around business operations, not CRUD
- Consider returning a union of success/error types
- 使用单一输入参数模式:
mutation(input: InputType!) - 在Mutation响应中返回受影响的对象
- 围绕业务操作设计Mutation,而非CRUD
- 考虑返回成功/错误类型的联合类型
ID Strategy
ID策略
- Use globally unique IDs when possible
- Implement interface for refetchability
Node - Base64-encode compound IDs if needed
- 尽可能使用全局唯一ID
- 实现接口以支持重新获取
Node - 如有需要,对复合ID进行Base64编码
Ground Rules
基础规则
- ALWAYS add descriptions to types and fields
- ALWAYS use non-null (!) for fields that cannot be null
- ALWAYS use [Type!]! pattern for lists
- NEVER expose database internals in schema
- NEVER break backwards compatibility without deprecation
- PREFER dedicated input types over many arguments
- PREFER enums over arbitrary strings for fixed values
- USE type for identifiers, not
IDorStringInt - USE custom scalars for domain-specific values (DateTime, Email, URL)
- 始终为类型和字段添加描述
- 始终为不可能为null的字段使用非空标记(!)
- 始终对列表使用**[Type!]!**模式
- 绝不向Schema暴露数据库内部细节
- 绝不未经废弃就破坏向后兼容性
- 优先使用专用输入类型而非多个参数
- 优先使用枚举类型而非任意字符串表示固定值
- 使用类型作为标识符,而非
ID或StringInt - 对领域特定值使用自定义标量(DateTime、Email、URL)