graphql-schema

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GraphQL 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

可空性规则

PatternMeaning
StringNullable - 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
undefined
graphql
undefined

Output 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! }
undefined
type Mutation { createUser(input: CreateUserInput!): User! }
undefined

Interface 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
    Node
    interface for refetchability
  • 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
    ID
    type for identifiers, not
    String
    or
    Int
  • USE custom scalars for domain-specific values (DateTime, Email, URL)
  • 始终为类型和字段添加描述
  • 始终为不可能为null的字段使用非空标记(!
  • 始终对列表使用**[Type!]!**模式
  • 绝不向Schema暴露数据库内部细节
  • 绝不未经废弃就破坏向后兼容性
  • 优先使用专用输入类型而非多个参数
  • 优先使用枚举类型而非任意字符串表示固定值
  • 使用
    ID
    类型作为标识符,而非
    String
    Int
  • 对领域特定值使用自定义标量(DateTime、Email、URL)