Введение

Мы хорошо знакомы с тем, что 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/