GraphQL: Query и Mutation
Query и Mutation — два основных типа операций GraphQL: Query читает данные (аналог GET), Mutation изменяет данные (аналог POST/PUT/DELETE).
Зачем нужно
Явное разделение на Query и Mutation задаёт намерение операции на уровне языка, позволяет серверу применять разные политики кэширования, авторизации и оптимизации. Понимание синтаксиса позволяет писать корректные запросы и мутации с переменными.
Где используется
- Клиентские приложения с Apollo Client, urql, React Query
- Серверные GraphQL resolver-функции на Node.js (Apollo Server, graphql-yoga)
- GraphQL Playground / GraphiQL для ручного тестирования API
Query — чтение данных
# Именованный запрос с переменной
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
title
createdAt
}
}
}
# Анонимный запрос (можно, но не рекомендуется в продакшне)
{
users {
id
name
}
}
# Алиасы — два поля с одним именем в разных вызовах
query TwoUsers {
alice: user(id: 1) { name }
bob: user(id: 2) { name }
}
# Фрагменты — переиспользование набора полей
fragment UserFields on User {
id
name
email
}
query GetUsers {
activeUsers: users(status: ACTIVE) { ...UserFields }
admins: users(role: ADMIN) { ...UserFields }
}
Mutation — изменение данных
# Создание
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
email
createdAt
}
}
# Обновление
mutation UpdateUser($id: ID!, $name: String!) {
updateUser(id: $id, name: $name) {
id
name
}
}
# Удаление
mutation DeleteUser($id: ID!) {
deleteUser(id: $id) {
success
message
}
}
Выполнение через fetch
async function graphqlRequest(query, variables = {}) {
const res = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables }),
});
const { data, errors } = await res.json();
if (errors?.length) throw new Error(errors[0].message);
return data;
}
// Query
const { user } = await graphqlRequest(
`query GetUser($id: ID!) { user(id: $id) { id name } }`,
{ id: '42' }
);
// Mutation
const { createUser } = await graphqlRequest(
`mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) { id name }
}`,
{ input: { name: 'Антон', email: 'anton@example.com' } }
);
Частые ошибки
- Использование Query для операций изменения данных — нарушает семантику и кэширование
- Не передают переменные — конкатенируют значения в строку (уязвимость инъекций)
- Не проверяют поле
errorsв ответе — HTTP-статус всегда 200 - Запрашивают все поля (включая тяжёлые связи) без необходимости — N+1 проблема
Связанные темы
- _MOC Сеть
- GraphQL -- основы и отличия от REST
- GraphQL -- Schema и типы
- GraphQL -- клиентские библиотеки
- REST API