GraphQL Essentials
Schema, queries, mutations, subscriptions, resolvers, N+1 problem.
graphqlapibackend
# GraphQL Essentials
## Schema (SDL)
```graphql
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
type Query {
user(id: ID!): User
users: [User!]!
}
type Mutation {
createPost(title: String!, authorId: ID!): Post!
}
```
## Query
```graphql
query GetUser($id: ID!) {
user(id: $id) { name posts { title } }
}
```
## Resolvers (Node.js)
```ts
const resolvers = {
Query: { user: (_, { id }, ctx) => ctx.db.users.findById(id) },
User: { posts: (parent, _, ctx) => ctx.db.posts.findByAuthor(parent.id) },
Mutation: { createPost: (_, args, ctx) => ctx.db.posts.create(args) },
}
```
## N+1 & DataLoader
Each field resolver triggers a separate DB query. Fix with DataLoader:
```ts
const loader = new DataLoader(ids => db.posts.findByAuthors(ids))
User: { posts: (p) => loader.load(p.id) }
```
## Pagination (Relay cursor spec)
```graphql
users(first: 10, after: "cursor") {
edges { node { id name } cursor }
pageInfo { hasNextPage endCursor }
}
```
## Errors
GraphQL always returns HTTP 200. Errors live in `errors[]`. Use `extensions.code` for machine-readable codes.
## Fragments
```graphql
fragment UserFields on User { id name }
query { a: user(id:"1") { ...UserFields } b: user(id:"2") { ...UserFields } }
```API: /api/skills/graphql-essentials