こんにちは、ソリューションの五十嵐です。
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の実行環境が表示されます。
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を実装できますので、ぜひ試してみてはいかがでしょうか。