
使用 Apollo Server 4 搭建 GraphQL 服务器
const typeDefs = gql`
type User { id: ID!; email: String!; posts: [Post!]! }
type Post { id: ID!; title: String!; author: User! }
type Query { users: [User!]!; user(id: ID!): User }
type Mutation { createPost(title: String!, content: String!): Post! }
`
const resolvers = {
Query: {
users: () => db.user.findMany(),
user: (_, { id }) => db.user.findUnique({ where: { id } }),
},
Mutation: {
createPost: async (_, args, { user }) => {
if (!user) throw new GraphQLError('Unauthorized', { extensions: { code: 'UNAUTHENTICATED' } })
return db.post.create({ data: { ...args, authorId: user.id } })
},
},
User: {
posts: (user) => db.post.findMany({ where: { authorId: user.id } }),
},
}
DataLoader:消除 N+1 查询
const userLoader = new DataLoader(async (ids) => {
const users = await db.user.findMany({ where: { id: { in: [...ids] } } })
return ids.map(id => users.find(u => u.id === id) ?? null)
})
// 每个请求一个 loader,防止跨请求缓存
context: () => ({ loaders: { user: new DataLoader(batchFn) } })
订阅
const pubsub = new PubSub()
const resolvers = {
Subscription: {
postCreated: { subscribe: () => pubsub.asyncIterator(['POST_CREATED']) },
},
Mutation: {
createPost: async (_, args) => {
const post = await db.post.create({ data: args })
pubsub.publish('POST_CREATED', { postCreated: post })
return post
},
},
}
-> 使用 JSON 查看器 测试 GraphQL 响应。