graphql

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GraphQL — Apollo Federation, Schema Design

GraphQL — Apollo Federation、Schema设计

API GraphQL moderne avec federation, DataLoader, optimisations.
现代化GraphQL API(含联邦架构、DataLoader、优化方案)

GraphQL vs REST

GraphQL vs REST

GraphQL — 1 query sur-mesure, no versioning, introspection auto
REST — Multiple endpoints, over-fetching, v1/v2/v3
GraphQL — 按需查询,无版本控制,支持自动自省
REST — 多端点,过度获取数据,存在v1/v2/v3版本迭代

Apollo Federation

Apollo Federation

graphql
undefined
graphql
undefined

Users service

Users service

type User @key(fields: "id") { id: ID!, name: String! }
type User @key(fields: "id") { id: ID!, name: String! }

Orders service

Orders service

extend type User @key(fields: "id") { id: ID! @external orders: [Order!]! }

Gateway compose automatiquement les services.
extend type User @key(fields: "id") { id: ID! @external orders: [Order!]! }

网关会自动组合各服务。

N+1 Problem — DataLoader

N+1问题 — DataLoader

javascript
// ❌ N+1 queries
User: { orders: (u) => db.orders.findByUserId(u.id) }

// ✅ DataLoader batch
const loader = new DataLoader(async (ids) => {
  const orders = await db.orders.findByUserIds(ids);
  return ids.map(id => orders.filter(o => o.userId === id));
});
User: { orders: (u) => loader.load(u.id) }
javascript
// ❌ N+1查询
User: { orders: (u) => db.orders.findByUserId(u.id) }

// ✅ DataLoader批量处理
const loader = new DataLoader(async (ids) => {
  const orders = await db.orders.findByUserIds(ids);
  return ids.map(id => orders.filter(o => o.userId === id));
});
User: { orders: (u) => loader.load(u.id) }

Patterns

设计模式

Pagination (Relay)

分页(Relay规范)

graphql
type UserConnection {
  edges: [{ node: User!, cursor: String! }]!
  pageInfo: { hasNextPage: Boolean!, endCursor: String }!
}
graphql
type UserConnection {
  edges: [{ node: User!, cursor: String! }]!
  pageInfo: { hasNextPage: Boolean!, endCursor: String }!
}

Error Handling

错误处理

graphql
type CreateUserPayload {
  user: User
  errors: [{ field: String, message: String! }]
}
graphql
type CreateUserPayload {
  user: User
  errors: [{ field: String, message: String! }]
}

Optimizations

优化方案

DataLoader — Batch + cache
Persisted Queries — Hash lookup
Depth Limiting — Anti-DoS
Cost Analysis — Query budget

Voir
@api-designer
pour design
DataLoader — 批量处理 + 缓存
持久化查询(Persisted Queries) — 哈希查找
深度限制(Depth Limiting) — 防DoS攻击
成本分析(Cost Analysis) — 查询预算

详见
@api-designer
进行设计