Как настроить мощный API с помощью GraphQL, Koa и MongoDB

Как настроить мощный API с помощью GraphQL, Koa и MongoDB

Создавать API весело! Особенно, когда вы можете использовать современные технологии, такие как Koa, GraphQL и MongoDB.

Koa – это фреймворк Node, точно так же, как и Express является фреймворком Node. Мы заменим Express на Koa, так как Koa использует синтаксис async/await вместо “коллбэков”.

Заметка; Если вы новичок в API, я рекомендую прочитать эту книгу, чтобы начать работу.

Начинаем

Необходимые условия для создания нашего API:

  • Node установлен
  • Текстовый редактор (я использую код Visual Studio)
  • Терминал
  • Браузер

Если у вас есть все, что вам нужно, продолжайте – если нет, пожалуйста, установите их.

Откройте свой терминал и создайте проект node, например, такой:

node project terminal

Итак, мы создали папку нашего проекта и инициализировали новый проект Node. Теперь у нас есть доступные пакеты NPM, которые мы можем использовать для установки Koa, Mongo и GraphQL.

Давайте установим коа с NPM.

npm i koa

Запустить новый сервер Koa просто. Все, что нам нужно – это файл server.js со следующим содержимым:

const Koa = require('koa');

const app = new Koa();

app.listen(9000);

app.on('error', err => {
  log.error('server error', err)
});

Начать проект с Node:

begin node project

Установка GraphQL

Нам нужны два пакета для настройки GraphQL с Koa: koa-mount и koa-graphql

npm i koa-mount koa-graphql

GraphQL требует, чтобы мы передали нашу исходную схему на сервер GraphQL. Давайте создадим один.

Мы помещаем схему graphQL в graphql/schema.js

const { buildSchema } = require('graphql');

const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

module.exports = schema;

Мы передаем наш начальный Query функции buildSchema.

app.use(mount('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true
})))

Примечание: аргумент для buildSchema является литералом шаблона.

Теперь мы можем передать исходную схему на наш сервер GraphQL:

const mount = require('koa-mount');
const graphqlHTTP = require('koa-graphql');
const schema = require('./graphql/schema')

Не забудьте импортировать koa-mount, koa-graphql и, наконец, schema.js.

И затем, если мы перейдем к localhost:9000/graphql:

localhost page

Вуаля! Начальная настройка завершена. Пока она не очень полезна – в идеале, мы хотели бы запросить GraphQL, чтобы сохранить данные в нашей MongoDB и прочитать их оттуда.

Настройка MongoDB

Чтобы читать и писать с помощью GraphQL, нам нужно место для чтения. Здесь Mongo как раз и пригодится. Мы будем сохранять и читать наши данные оттуда.

Чтобы упростить ситуацию, мы будем использовать облачный экземпляр для Mongo. Зайдите на mlab.com и создайте базу данных пользователей и монго.

Создание базы данных MongoDB

creating MongoDB database

creating koa graphql database

mongo shell connect

После того, как вы создали базу данных, вам потребуется пользователь для базы данных.

Создание пользователя MongoDB

Нажмите на вкладку пользователей и создайте новое имя пользователя с паролем.

add-new-database-user

Теперь вы можете использовать mongoDB в паре с Mongoose. Удаленный URL для вашей базы данных будет выглядеть примерно так:

MongoDB: //: @ ds213615.mlab.com: 13615 / КоА-graphql
Установка mongoose
npm i mongoose
Создание файла database.js

Мы создаем специальный файл для подключения к базе данных:

const mongoose = require('mongoose');

const initDB = () => {

  mongoose.connect(
    'mongodb://indrek:graphql1@ds213615.mlab.com:13615/koa-graphql',
    { useNewUrlParser: true }
  );

  mongoose.connection.once('open', () => {
    console.log('connected to database');
  });

}

module.exports = initDB;

Примечание. Убедитесь, что вы используете имя пользователя и учетные данные для своей базы данных.

Этот блок кода попытается подключиться к удаленному MongoDB..

Откройте server.js и require и запросите метод initDB.

const initDB = require('./database');

initDB();

Если мы все сделали правильно, наша консоль должна сообщить нам, что мы подключились успешно.

node connected to database

Браво!

Заметьте, как досадно постоянно обновлять сервер? Давайте решим это с помощью пакета pm2.

PM2 – это менеджер производственных процессов для приложений Node.js со встроенным балансировщиком нагрузки. Это позволяет вам поддерживать приложения в актуальном состоянии, перезагружать их без простоев и облегчать общие задачи системного администратора.

npm install pm2 -g

Добавьте скрипт с именем start в наш package.json:

"scripts": {
  "start": "pm2 start server.js"
},

api yarn start

Pm2 работает в фоновом режиме, что освобождает наш терминал. Если вы когда-нибудь захотите остановить процесс, просто запустите pm2 kill. Теперь нам не нужно постоянно перезагружать наш сервер, pm2 делает это автоматически.

Примечание: pm2 logs возвращает выражения журнала консоли на терминал.

Модели MongoDB

Если вы когда-либо работали с Mongo, вы знаете, что MongoDB позволяет нам создавать модели для наших данных. Это отличный способ структурировать наши данные.

Создайте папку для моделей MongoDB и внутри файла gadgets.js:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

/*
  notice there is no ID. That's because Mongoose will assign
  an ID by default to all schemas
*/

const GadgetSchema = new Schema({
  name: String,
  release_date: Date,
  by_company: String,
  price: Number,
});

module.exports = mongoose.model('Gadget', GadgetSchema);

Примечание. В нашей схеме нет поля идентификатора. Это потому, что Mongoose назначит идентификатор по умолчанию для всех схем.

Отлично, теперь давайте добавим коллекцию и несколько фиктивных данных. Название коллекции должно отображать имя нашего гаджета во множественном числе, в данном случае gadgets.

gadgets-collection-name

После создания коллекции вставьте документ в формате JSON следующим образом:

create-document-json

Это все для Mongo, теперь давайте получим данные с помощью GraphQL.

Запросы GraphQL

GraphQL также требует от нас создания типов (наподобие инструкций для компьютеров).

graphql/gadgetType.js
const graphql = require('graphql');

const { GraphQLObjectType, GraphQLString } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({

  })
});

module.exports = GadgetType;

Обратите внимание, что мы создали тип graphql. Внутри полей мы можем указать свойства данного типа.

const graphql = require('graphql');

const { GraphQLObjectType, GraphQLObjectType } = graphql;

const GadgetType = new GraphQLObjectType({
  name: 'Gadget',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    release_date: { type: GraphQLString },
    by_company: { type: GraphQLString },
    price: { type: GraphQLString }
  })
});

module.exports = GadgetType;

Обратите внимание на типы GraphQLObjectType и GraphQLObjectType, которые мы деконструируем из graphQL. Это примитивные типы для graphQL.

Создание типов GraphQL также предоставляет подсказки типов, которые мы будем использовать при создании наших запросов.

Последнее, что нам нужно сделать – это рефакторинг нашего schema.js. Мы хотим запросить гаджет по id.

Импортируйте модель Gadget, gadgetGraphQLType graphql типа и GraphQLSchema, GraphQLObjectType, GraphQLString из graphQL в schema.js.

const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require('graphql');
const gadgetGraphQLType =  require('./gadgetType');
const Gadget = require('../models/gadget');

Далее нам нужен корневой запрос. Каждый запрос GraphQL начинается с фигурных скобок {} – это корневой запрос.

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {

  }
})

Вуаля! Внутри полей мы можем указать gadget запрос.

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(<a href="http://args.id" class="link link-url" target="_blank" rel="external nofollow noopener noreferrer">args.id</a>)
      }
    }
  }
})

Обратите внимание на три свойства внутри запроса гаджета:

  • тип – это тип запроса, в данном случае gadgetGraphQLType.
  • аргументы – мы можем предоставить аргументы для запросов graphql, например: gadgets (id: “1”)
  • решение – как мы хотим разрешить запрос? Что должно произойти после выполнения запроса? Здесь мы возвращаем модель гаджета по id.

И наконец, экспортируйте.

module.exports = new GraphQLSchema({
  query: RootQuery
});

Файл schema.js должен выглядеть следующим образом.

const { GraphQLSchema, GraphQLObjectType, GraphQLString} = require('graphql');
const gadgetGraphQLType =  require('./gadgetType');
const Gadget = require('../models/gadget');

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    gadget: {
      type: gadgetGraphQLType,
      args: { id: { type: GraphQLString }},
      resolve(parent, args) {
        return Gadget.findById(<a href="http://args.id" class="link link-url" target="_blank" rel="external nofollow noopener noreferrer">args.id</a>)
      }
    }
  }
})

module.exports = new GraphQLSchema({
  query: RootQuery
});

Теперь зайдите на http://localhost:9000/graphql и сделайте запрос.

{
    gadget(id: "5c4e188efb6fc05326ad9264") {
        name
    price
    by_company
    release_date
    id
  }
}

Это то, что мы должны в конечном итоге:

QraphQl-gadget-code

Спасибо за чтение! ❤

 


.

  • December 20, 2019