Connecting Schemas and Resolvers
Apollo Server connects a GraphQL schema with resolver implementations.
Consider this schema:
type Query {
hello: String!
user(id: ID!): User
}
type User {
id: ID!
name: String!
}
The resolver map can mirror the schema structure:
const resolvers = {
Query: {
hello: () => "Hello GraphQL",
user: (_, { id }, context) => {
return context.userService.findById(id);
}
}
};
The Query property corresponds to the root Query type. The hello and user properties correspond to fields on that type.
Nested types can have their own resolver maps:
const resolvers = {
Query: {
user: (_, { id }, context) => context.userService.findById(id)
},
User: {
fullName: (user) => `${user.firstName} ${user.lastName}`
}
};
The resolver map therefore acts as a runtime implementation of the schema.
A useful rule is to keep schema definitions descriptive and resolver implementations focused. Avoid putting database queries, authentication parsing, validation, transformation, and business workflows into a single resolver function.
Schema and Resolver Map
const typeDefs = `
type User {
id: ID!
name: String!
}
type Query {
user(id: ID!): User
}
`;
const resolvers = {
Query: {
user: (_, { id }, context) => {
return context.userService.findById(id);
}
}
};💡 The
Query.user resolver receives the requested ID and delegates data retrieval to an application service. The GraphQL layer therefore remains separate from the underlying persistence implementation.Key Takeaways
- Resolver maps mirror GraphQL schema types and fields.
- Root operations are implemented under
Query,Mutation, andSubscription. - Nested object types can have their own resolver maps.
- Keep resolver functions focused on orchestration.
Knowledge Check
Where is the resolver for a field named `user` on the root `Query` type normally placed?