name: graphql description: 设计GraphQL模式、解析器和联邦。用于GraphQL API设计或性能问题。
GraphQL 开发
设计高效的GraphQL API。
何时使用
- 创建GraphQL模式
- 解析器实现
- N+1查询问题
- 联邦/缝合
- 性能优化
模式设计
type Query {
user(id: ID!): User
users(filter: UserFilter, limit: Int = 10): UserConnection!
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}
type User {
id: ID!
email: String!
name: String!
posts(first: Int, after: String): PostConnection!
createdAt: DateTime!
}
input CreateUserInput {
email: String!
name: String!
}
type CreateUserPayload {
user: User
errors: [Error!]
}
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type UserEdge {
node: User!
cursor: String!
}
type PageInfo {
hasNextPage: Boolean!
endCursor: String
}
解析器
const resolvers = {
Query: {
user: (_, { id }, { dataSources }) => dataSources.users.getById(id),
users: async (_, { filter, limit }, { dataSources }) => {
const users = await dataSources.users.find(filter, limit);
return connectionFromArray(users);
},
},
User: {
// Field resolver with DataLoader for N+1
posts: (user, args, { loaders }) => loaders.postsByUser.load(user.id),
},
Mutation: {
createUser: async (_, { input }, { dataSources }) => {
try {
const user = await dataSources.users.create(input);
return { user, errors: null };
} catch (e) {
return { user: null, errors: [{ message: e.message }] };
}
},
},
};
DataLoader (N+1 解决方案)
const DataLoader = require("dataloader");
const createLoaders = (dataSources) => ({
userById: new DataLoader(async (ids) => {
const users = await dataSources.users.getByIds(ids);
const userMap = new Map(users.map((u) => [u.id, u]));
return ids.map((id) => userMap.get(id) || null);
}),
postsByUser: new DataLoader(async (userIds) => {
const posts = await dataSources.posts.findByUserIds(userIds);
const grouped = groupBy(posts, "userId");
return userIds.map((id) => grouped[id] || []);
}),
});
性能提示
- 使用DataLoader进行批处理
- 实现查询复杂性限制
- 添加深度限制
- 使用Redis/CDN缓存
- 使用持久化查询
最佳实践
- 默认可为空,明确
!表示必需 - 为突变使用输入类型
- 返回包含错误的负载类型
- 实现游标分页
- 通过模式演化进行版本控制
示例
输入: “修复N+1查询” 操作: 实现DataLoader,批处理数据库查询
输入: “设计用户管理API” 操作: 创建包含类型、查询、突变、分页的模式