Что определяет GraphQL схема?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
GraphQL схема: что она определяет
GraphQL схема — это контракт между клиентом и сервером, который определяет все возможные данные и операции, доступные в API. Это как документация и валидатор одновременно.
Основное назначение GraphQL схемы
GraphQL схема определяет:
- Все доступные типы данных (Type definitions)
- Структуру данных (fields и их типы)
- Возможные запросы (Queries)
- Возможные изменения данных (Mutations)
- Подписки на события (Subscriptions)
- Правила валидации (требуемые поля, скаляры)
- Возможности и ограничения API
Пример простой GraphQL схемы
# Определение типа User
type User {
id: ID! # ! означает обязательное поле
name: String!
email: String!
age: Int
posts: [Post!]! # Массив обязательных Post
createdAt: DateTime!
}
# Определение типа Post
type Post {
id: ID!
title: String!
content: String
author: User! # Связь с User
comments: [Comment!]!
}
type Comment {
id: ID!
text: String!
author: User!
post: Post!
}
# Определение возможных запросов (Queries)
type Query {
user(id: ID!): User # Получить пользователя по ID
users(limit: Int = 10): [User!]! # Получить список пользователей
post(id: ID!): Post
posts(authorId: ID): [Post!]!
}
# Определение возможных мутаций (Mutations)
type Mutation {
createUser(name: String!, email: String!): User!
updateUser(id: ID!, name: String): User
deleteUser(id: ID!): Boolean!
createPost(title: String!, content: String!, authorId: ID!): Post!
}
# Подписки на события (Subscriptions)
type Subscription {
userCreated: User! # Событие при создании пользователя
postCommented(postId: ID!): Comment!
}
Что определяет GraphQL схема (детально)
1. Типы данных
Схема определяет все типы данных, которые может вернуть API:
type User {
id: ID! # Скалярный тип ID
name: String! # Строка
age: Int # Целое число
isActive: Boolean # Boolean
joinedAt: DateTime # Custom скалярный тип
email: String!
}
2. Обязательность полей
Восклицательный знак ! указывает, что поле обязательно (никогда не будет null):
# name всегда возвращает значение
name: String! # OK: "Иван"
# ОШИБКА: null
# age может быть null
age: Int # OK: 25
# OK: null
3. Массивы
Квадратные скобки обозначают массивы:
posts: [Post!]! # Массив (обязателен), элементы обязательны
posts: [Post]! # Массив (обязателен), элементы могут быть null
posts: [Post!] # Массив может быть null, элементы обязательны
posts: [Post] # Массив и элементы могут быть null
4. Операции (Queries, Mutations, Subscriptions)
Схема определяет, какие операции доступны:
# QUERY — получение данных (read)
query GetUser {
user(id: "123") {
id
name
email
}
}
# MUTATION — изменение данных (write)
mutation CreatePost {
createPost(
title: "Новая статья"
content: "Содержание..."
authorId: "456"
) {
id
title
author {
name
}
}
}
# SUBSCRIPTION — подписка на события (real-time)
subscription OnNewPost {
postCreated {
id
title
author {
name
}
}
}
Аргументы и фильтрация
Схема определяет, какие аргументы принимают запросы:
# Определение схемы
type Query {
posts(
limit: Int = 10 # Параметр с значением по умолчанию
offset: Int = 0
authorId: ID # Опциональный параметр
sortBy: String = "date"
): [Post!]!
}
# Пример запроса
query {
posts(limit: 20, authorId: "456", sortBy: "title") {
id
title
author { name }
}
}
Интерфейсы и union типы
Схема поддерживает абстрактные типы:
# Interface — контракт для других типов
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
}
type Post implements Node {
id: ID!
title: String!
}
# Union — тип может быть одним из нескольких
union SearchResult = User | Post | Comment
type Query {
search(query: String!): [SearchResult!]!
}
# Запрос к union типу
query {
search(query: "иван") {
... on User {
id
name
email
}
... on Post {
id
title
}
... on Comment {
id
text
}
}
}
Input типы для мутаций
Для сложных мутаций используются input типы:
# Определение input типа
input CreatePostInput {
title: String!
content: String!
tags: [String!]
published: Boolean = false
}
type Mutation {
createPost(input: CreatePostInput!): Post!
}
# Запрос
mutation {
createPost(input: {
title: "Заголовок"
content: "Текст"
tags: ["javascript", "react"]
published: true
}) {
id
title
}
}
Директивы
Схема определяет директивы для условного включения полей:
# Определение директивы
directive @deprecated(reason: String) on FIELD_DEFINITION
type User {
id: ID!
name: String!
fullName: String @deprecated(reason: "Используй name вместо этого")
}
# Использование в запросе
query {
user(id: "123") {
name
# Стандартные директивы: @skip и @include
email @include(if: $includeEmail)
phone @skip(if: $hidePhone)
}
}
Практический пример: REST API vs GraphQL схема
REST API:
GET /api/users/123
GET /api/users/123/posts
GET /api/users/123/posts/456/comments
Вам нужно 3 запроса!
GraphQL:
query {
user(id: "123") {
name
posts { # Связанные данные в одном запросе
title
comments { # Вложенные связи
text
author { name }
}
}
}
}
Один запрос!
Использование схемы в приложении
На сервере:
// Apollo Server
const typeDefs = `
type Query {
user(id: ID!): User
posts: [Post!]!
}
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
author: User!
}
`;
const resolvers = {
Query: {
user: (_, { id }) => fetchUser(id),
posts: () => fetchPosts()
},
User: {
posts: (user) => fetchUserPosts(user.id)
}
};
const server = new ApolloServer({ typeDefs, resolvers });
На клиенте:
import { gql, useQuery } from '@apollo/client';
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
posts {
id
title
}
}
}
`;
function UserProfile({ userId }) {
const { loading, data } = useQuery(GET_USER, { variables: { id: userId } });
// Данные будут соответствовать схеме
return <div>{data?.user?.name}</div>;
}
Резюме
GraphQL схема определяет:
- Типы данных — какие данные доступны
- Структуру — как связаны данные между собой
- Операции — какие query, mutation, subscription доступны
- Валидацию — обязательные/опциональные поля, типы
- Аргументы — какие параметры принимают операции
- Контракт — договор между клиентом и сервером
ГрафQL схема — это сердце GraphQL API. Она гарантирует, что и клиент, и сервер понимают друг друга и работают с одинаковыми данными. IDE автоматически подсказывает доступные поля и типы благодаря схеме.