GraphQL 查询(Query)、变更(Mutation)和订阅(Subscription)的区别
GraphQL 提供了三种主要的操作类型,每种类型都有特定的用途和语义。
1. 查询(Query)
定义: 用于获取数据,类似于 REST 中的 GET 请求。
特点:
- 只读操作,不会修改服务器上的数据
- 可以并行执行多个查询
- 可以嵌套查询以获取相关数据
- 可以使用参数来过滤或定制结果
示例:
graphqlquery GetUser($userId: ID!) { user(id: $userId) { id name email posts { id title createdAt } } }
使用场景:
- 获取用户信息
- 列表查询
- 数据详情展示
- 报表生成
2. 变更(Mutation)
定义: 用于修改服务器上的数据,类似于 REST 中的 POST、PUT、DELETE 请求。
特点:
- 会修改服务器上的数据
- 按顺序执行(串行),确保数据一致性
- 通常返回修改后的数据或操作结果
- 可以包含输入对象和参数
示例:
graphqlmutation CreateUser($input: CreateUserInput!) { createUser(input: $input) { id name email createdAt } } mutation UpdateUser($userId: ID!, $input: UpdateUserInput!) { updateUser(id: $userId, input: $input) { id name email updatedAt } } mutation DeleteUser($userId: ID!) { deleteUser(id: $userId) { success message } }
使用场景:
- 创建新资源
- 更新现有资源
- 删除资源
- 批量操作
3. 订阅(Subscription)
定义: 用于实时数据推送,当服务器端数据发生变化时,客户端会自动收到更新。
特点:
- 建立持久连接(通常使用 WebSocket)
- 服务器主动推送数据到客户端
- 适用于实时性要求高的场景
- 可以包含过滤条件
示例:
graphqlsubscription OnUserCreated { userCreated { id name email createdAt } } subscription OnPostUpdated($postId: ID!) { postUpdated(postId: $postId) { id title content updatedAt } }
使用场景:
- 聊天应用
- 实时通知
- 实时数据监控
- 协作编辑
核心区别对比
| 特性 | Query | Mutation | Subscription |
|---|---|---|---|
| 数据修改 | 只读 | 修改数据 | 只读 |
| 执行方式 | 并行 | 串行 | 持久连接 |
| 实时性 | 按需请求 | 按需请求 | 实时推送 |
| 网络协议 | HTTP | HTTP | WebSocket |
| 缓存 | 可缓存 | 不可缓存 | 不可缓存 |
| 幂等性 | 幂等 | 非幂等 | 非幂等 |
最佳实践
Query 最佳实践
- 避免过度获取,只请求需要的字段
- 使用参数进行数据过滤
- 合理使用分页
- 利用 GraphQL 的类型系统进行数据验证
Mutation 最佳实践
- 使用输入对象(Input Types)封装参数
- 返回修改后的完整数据
- 提供清晰的成功/失败响应
- 实现适当的错误处理和验证
Subscription 最佳实践
- 提供过滤条件减少不必要的数据推送
- 实现连接管理和重连机制
- 考虑使用负载均衡处理大量订阅
- 设置合理的超时和心跳机制
性能考虑
- Query: 使用 DataLoader 解决 N+1 查询问题
- Mutation: 使用事务确保数据一致性
- Subscription: 使用消息队列处理高并发订阅