【GraphQL+MongoDB】graphql-composeで簡単にGraphQL APIを実装する

こんにちは、ソリューションの五十嵐です。

MongoDB + GraphQLでデータを提供する案件に携わりました。

その際に使用したgraphql-composeというライブラリが素晴らしかったので記事にまとめます。

GraphQLとは

GraphQLはクライアントとサーバでのデータのやりとりに使用するクエリ言語です。

欲しいデータを過不足なく取得できるほか、学習コストが小さいなどのメリットがあります。

デメリットとしてサーバサイドの実装が難しいという情報が多いですが、 graphql-composeを使用することで簡単にCRUD機能を有するGraphQL APIを実装できます。

https://graphql-compose.github.io/

構成は以下の通りです。

Node.js
Express
MongoDB
Mongoose
GraphQL

Express

まずは必要なパッケージをインストールし、Expressのアプリケーションを作成します。

$ yarn add express

メインとなるserver.jsを実装していきましょう。

import express from 'express';
import bodyParser from 'body-parser';
// 使用ポートの設定
const PORT = 8080;
// Express初期化
const app = express();
app.use("/hello", (req, res) => {
    res.send('Hello World!')
});
app.listen(PORT, () => {
    console.log(`Started on port ${PORT}`)
});

server.jsを実行し、http://localhost:8080/helloにアクセスするとHello Worldが表示されます。

MongoDB

MongoDBとの接続を行います。

Mongooseを使用したいので、以下のコマンドで必要なパッケージをインストールしましょう。

$ yarn add mongodb mongoose

次にutilsディレクトリを作成し、その中にDBとの接続を行うdatabase.jsを作成します。

$ mkdir utils

utils/database.js

import mongoose from 'mongoose';
const DB = {
    connect: () => {
        const host = 'localhost'; // ホスト
        const user = 'root'; // ユーザー
        const password = 'password'; // パスワード
        const database = 'graphql_database'; // データベース名
        mongoose.connect(`mongodb://${user}:${password}@${host}/${database}`, { useNewUrlParser: true });
    }
}
export default DB;

database.jsをimportし、DB.connect()を実行することでMongoDBに接続されるようになりました。

import DB from 'utils/database.js';
DB.connect();

GraphQL

GraphQLを実装していきます。

まずはGraphQL関連の必要パッケージをインストールします。

$ yarn add graphql express-graphql graphql-compose graphql-compose-mongoose

スキーマとモデルのディレクトリを作成します。

$ mkdir models schemata

今回はサンプルとして本のタイトルと著者のデータとします。

タイトルと著者をString型として定義したモデルを作成します。

models/book.js

import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const BookModel = new Schema({
    title: String, // タイトル
    author: String // 著者
});
export default mongoose.model('Book', BookModel);

さらにスキーマも作成します。

ここで本記事の主役であるgraphql-composeを使用します。

graphql-composeはGraphQLのスキーマを作成するToolkitとのことで、 簡単にスキーマを作成することができます。

schemata/book.js

import { schemaComposer } from 'graphql-compose';
import BookModel from '../models/book.js';
import { composeWithMongoose } from 'graphql-compose-mongoose';
const customizationOptions = {};
const Book = composeWithMongoose(BookModel, customizationOptions);
schemaComposer.Query.addFields({
    bookById: Book.getResolver('findById'), // IDでの1件取得
    bookByIds: Book.getResolver('findByIds'), // 複数IDでの検索
    bookOne: Book.getResolver('findOne'), // データ1件取得
    bookMany: Book.getResolver('findMany'), // データ複数件取得
    bookCount: Book.getResolver('count'), // データ件数取得
    bookConnection: Book.getResolver('connection'), // ?
    bookPagination: Book.getResolver('pagination') // データのページ送り
});
schemaComposer.Mutation.addFields({
    bookCreate: Book.getResolver('createOne'), // データ作成1件
    bookCreateMany: Book.getResolver('createMany'), // データ作成複数件
    bookUpdateById: Book.getResolver('updateById'), // IDでのデータ更新
    bookUpdateOne: Book.getResolver('updateOne'), // データ更新1件
    bookUpdateMany: Book.getResolver('updateMany'), // データ更新複数件
    bookRemoveById: Book.getResolver('removeById'), // IDでのデータ削除
    bookRemoveOne: Book.getResolver('removeOne'), // データ削除1件
    bookRemoveMany: Book.getResolver('removeMany') // データ削除複数件
});
export default schemaComposer.buildSchema();

これだけでCRUDのGraphQL APIになります。

最後にserver.jsを修正してGraphQLを有効にします。

server.js

import DB from './utils/database.js';
DB.connect();
import graphqlExpress from 'express-graphql';
import schema from './schemata/book.js';
app.use(
    "/graphql",
    bodyParser.json(),
    graphqlExpress({ schema, graphiql: true })
);

再度server.jsを実行して以下のURLを開いてみましょう、GraphQLの実行環境が表示されます。

http://localhost:8080/graphql

DBにデータが存在していないのでGraphQLでデータを新規登録してみます。

【GraphQL+MongoDB】graphql-composeで簡単にGraphQL APIを実装する実行環境の左上に以下のmutationを入力します。

mutation createBook($input: CreateOneBookInput!) {
  bookCreate(record: $input) {
    recordId
  }
}

さらに左下のQUERY VARIABLESの部分に以下を入力し実行しましょう。

{
  "input": {
    "title": "TestBook",
    "author": "TestAuthor"
  }
}

作成されたデータのIDがレスポンスとして返却されます。

データが作成できましたのでGraphQLでデータを取得してみます。

実行環境の左上に以下のqueryを入力して実行してみます。

query getBook {
  bookOne {
    _id
    title
    author
  }
}

queryで指定した通り、_id, title, authorが取得できました。

まとめ

GraphQLにはログイン認証や画像等のデータの扱いなど、課題が多いですがメリットも大きいと思います。

graphql-composeで簡単にGraphQL APIを実装できますので、ぜひ試してみてはいかがでしょうか。

コメントを残す

メールアドレスが公開されることはありません。*がついている欄は必須項目です。

日本語が含まれない投稿は無視されますのでご注意ください。