Введение
Мы хорошо знакомы с тем, что GraphQL является языком запросов. Это среда выполнения на стороне сервера, которая обычно обслуживается через HTT. Мы используем GraphQL для запроса данных, начиная с любого количества измененных источников. Здесь мы обсуждаем запросы и мутации Graphql
В этом посте мы обсудим операцию мутаций GraphQL и попытаемся рассказать, что такое мутации, как они соотносятся с запросами и когда их использовать.
Описание
В GraphQL можно выполнять только два типа операций:
- Запросы: мы используем запросы для получения данных
- Мутации: мы используем мутации для настройки данных на стороне сервера.
- Мутации означают методы изменения состояния в REST, например DELETE, PUT, PATCH, если запросы являются GraphQL эквивалентными вызовам GET в REST.
- В обсуждениях GraphQL особое внимание уделяется выборке данных. Хотя любая всеобъемлющая платформа данных также требует способа изменения данных на стороне сервера.
- Любой запрос может привести к некоторым побочным эффектам на сервере в REST.
- С другой стороны, по соглашению необязательно использовать запросы GET для корректировки данных.
- GraphQL технически связан с любым запросом, который может быть применен для записи данных.
- Тем не менее, важно установить соглашение о том, что любые процессы, вызывающие запись, должны отправляться открыто с помощью мутации.
- Мы можем запросить вложенные поля, как и в запросах, если поле мутации возвращает тип объекта.
- Это может быть удобно для получения нового состояния объекта после обновления.
Пример:
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars commentary } } { "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" } } { "data": { "createReview": { "stars": 5, "commentary": "This is a great movie!" } } }
- Важно отметить, каким образом поле createReview возвращает звезды и поля комментариев только что сделанного обзора.
- Это особенно полезно при изменении текущих данных.
- Например, при увеличении поля.
- На данный момент мы можем изменить и запросить новое значение поля одним запросом.
- На этом рисунке переменная обзора, которую мы передали, не является скаляром.
- Это тип объекта ввода. Это особый тип объекта, и его можно передавать в качестве аргумента.
Разница между запросом и мутацией
- Одно фактическое различие между запросом и мутацией, во всяком случае, носит структурный характер.
- Эта разница заключается в типе операции.
- Мы практикуем слово запрос для запросов.
- Мы используем слово «мутация» для обозначения мутаций.
- Еще одна важная вещь, которую следует отметить, это то, что мы сигнализируем о мутации.
- Нам нужно вызвать его, назвав его правильно, как это происходит в нашем API GraphQL на стороне сервера.
Мутации и типы ввода
- Мы должны сделать конечную точку API мутацией, а не запросом, который изменяет данные. Например, вставка данных в базу данных или изменение данных, уже находящихся в базе данных.
- Это так же скромно, как создание конечной точки API типа Mutation верхнего уровня в качестве альтернативы типу Query верхнего уровня.
- Предположим, что у нас есть сообщение дневного сервера. Любой может обновить сообщение дня, и любой может прочитать текущее. Схема GraphQL для этого только:
type Mutation { setMessage(message: String): String } type Query { getMessage: String }
- Очень часто удобно иметь мутацию, которая сопоставляется с операцией создания или обновления базы данных.
- Например, setMessage дает то же самое, что хранит сервер.
- Так клиент может узнать об этих изменениях, если мы скорректируем данные на сервере.
- Вместе мутации и запросы могут обрабатываться корневыми преобразователями.
- Следовательно, корень, реализующий эту схему, может быть просто:
var fakeDatabase = {}; var root = { setMessage: ({message}) => { fakeDatabase.message = message; return message; }, getMessage: () => { return fakeDatabase.message; } };
- Для реализации мутаций нам не требуется ничего большего, чем это.
- Мы найдем множество разнообразных мутаций, которые принимают одни и те же входные параметры.
- Простой иллюстрацией является то, что создание объекта в базе данных и обновление объекта в базе данных обычно принимают одни и те же параметры.
- Для этого мы можем использовать входные типы, чтобы упростить схему. Это может произойти при использовании ключевого слова input в качестве альтернативы ключевому слову type.
Пример
- Предположим, у нас есть множество сообщений вместо одного сообщения дня.
- Они индексируются в базе данных по полю id.
- Каждое сообщение имеет вместе строку содержимого и строку автора.
- Нам нужен API-интерфейс мутации для создания нового сообщения и для обновления старого сообщения. Мы можем использовать схему:
input MessageInput { content: String author: String } type Message { id: ID! content: String author: String } type Query { getMessage(id: ID!): Message } type Mutation { createMessage(input: MessageInput): Message updateMessage(id: ID!, input: MessageInput): Message }
- Мутации возвращают здесь тип сообщения, чтобы клиент мог получить больше информации.
- Эта информация относится к недавно измененному сообщению в запросе, аналогичном запросу, который его изменяет.
- Как и другие объекты, типы ввода не могут иметь полей.
- Именование типов ввода с помощью Input в конце является полезным соглашением.
- Как мы будем неоднократно хотеть вместе с типом ввода и типом вывода, которые несколько отличаются для одного концептуального объекта.
- Сохранение данных в памяти примерно соответствует исполняемому коду, который реализует эту схему:
var express = require('express'); var { graphqlHTTP } = require('express-graphql'); var { buildSchema } = require('graphql'); // Make a schema, using GraphQL schema language var schema = buildSchema(` input MessageInput { content: String author: String } type Message { id: ID! content: String author: String } type Query { getMessage(id: ID!): Message } type Mutation { createMessage(input: MessageInput): Message updateMessage(id: ID!, input: MessageInput): Message } `); // If Message had any complex fields, we'd put them on this object. class Message { constructor(id, {content, author}) { this.id = id; this.content = content; this.author = author; } } // Maps username to content var fakeDatabase = {}; var root = { getMessage: ({id}) => { if (!fakeDatabase[id]) { throw new Error('no message exists with id ' + id); } return new Message(id, fakeDatabase[id]); }, createMessage: ({input}) => { // Create a random id for our "database". var id = require('crypto').randomBytes(10).toString('hex'); fakeDatabase[id] = input; return new Message(id, input); }, updateMessage: ({id, input}) => { if (!fakeDatabase[id]) { throw new Error('no message exists with id ' + id); } // This replaces all old data, but some apps might want partial update. fakeDatabase[id] = input; return new Message(id, input); }, }; var app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, })); app.listen(4000, () => { console.log('Running a GraphQL API server at localhost:4000/graphql'); }); Visit website for more intresting blog posts
Для получения более подробной информации посетите: https://www.technologiesinindustry4.com/graphql-queries-and-mutations/