著者は、ウィキメディア財団を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

GraphQLは、さまざまなデータコレクションからのデータのクエリと変更を容易にするAPIのクエリ言語として、2015年にFacebookによって公開されました。 単一のエンドポイントから、単一のPOSTリクエストで複数のデータソースをクエリおよび変更できます。 GraphQLは、エンドポイントが実際に必要な情報よりも多くの情報を返す状況など、RESTAPIアーキテクチャーの一般的な設計上の欠陥のいくつかを解決します。 また、REST APIを使用する場合、必要なすべての情報を収集するために複数のRESTエンドポイントにリクエストを送信する必要がある可能性があります。これはn+1問題と呼ばれる状況です。 この例としては、ユーザーの情報を表示したいが、個人情報や住所などのデータをさまざまなエンドポイントから収集する必要がある場合があります。

複数のコレクションからデータを返すことができるエンドポイントが1つしかないため、これらの問題はGraphQLには当てはまりません。 返されるデータは、このエンドポイントに送信するqueryによって異なります。 このクエリでは、ネストされたデータコレクションを含め、受信するデータの構造を定義します。 クエリに加えて、 mutation を使用してGraphQLサーバー上のデータを変更したり、Subscriptionを使用してデータの変更を監視したりすることもできます。 GraphQLとその概念の詳細については、公式Webサイトのドキュメントにアクセスしてください。

GraphQLは柔軟性の高いクエリ言語であるため、MongoDBなどのドキュメントベースのデータベースと特にうまく組み合わせることができます。 どちらのテクノロジーも、階層型の型付きスキーマに基づいており、JavaScriptコミュニティ内で人気があります。 また、MongoDBのデータはJSONオブジェクトとして保存されるため、GraphQLサーバーで追加の解析は必要ありません。

このチュートリアルでは、Ubuntu18.04で実行されているMongoDBデータベースからデータをクエリおよび変更できるNode.jsを使用してGraphQLサーバーを構築およびデプロイします。 このチュートリアルの最後に、単一のエンドポイントを使用して、ターミナルを介してサーバーに直接リクエストを送信することと、事前に作成されたGraphiQLプレイグラウンドインターフェイスを使用することの両方で、データベース内のデータにアクセスできるようになります。 この遊び場では、クエリ、ミューテーション、サブスクリプションを送信することで、GraphQLサーバーのコンテンツを探索できます。 また、このサーバー用に定義されているスキーマの視覚的表現を見つけることができます。

このチュートリアルの最後に、GraphiQLプレイグラウンドを使用して、GraphQLサーバーとすばやくインターフェースします。

The GraphiQL playground in action

前提条件

このガイドを開始する前に、次のものが必要です。

ステップ1—MongoDBデータベースのセットアップ

GraphQLサーバーを作成する前に、データベースが正しく構成され、認証が有効になっていて、サンプルデータが入力されていることを確認してください。 このためには、コマンドプロンプトからMongoDBデータベースを実行しているUbuntu18.04サーバーに接続する必要があります。 このチュートリアルのすべての手順は、このサーバーで実行されます。

接続を確立したら、次のコマンドを実行して、MongoDBがアクティブでサーバー上で実行されているかどうかを確認します。

sudo systemctl status mongodb

ターミナルに次の出力が表示され、MongoDBデータベースがアクティブに実行されていることを示します。

Output
● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago Docs: man:mongod(1) Main PID: 2388 (mongod) Tasks: 25 (limit: 1152) CGroup: /system.slice/mongodb.service └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

サンプルデータを保存するデータベースを作成する前に、まず admin ユーザーを作成する必要があります。これは、通常のユーザーが特定のデータベースにスコープされているためです。 これを行うには、MongoDBシェルを開く次のコマンドを実行します。

mongo

MongoDBシェルを使用すると、MongoDBデータベースに直接アクセスでき、ユーザーまたはデータベースを作成してデータをクエリできます。 このシェル内で、新しいadminユーザーをMongoDBに追加する次のコマンドを実行します。 強調表示されたキーワードを独自のユーザー名とパスワードの組み合わせに置き換えることができますが、どこかに書き留めることを忘れないでください。

use admin
db.createUser({
    user: "admin_username",
    pwd: "admin_password",
    roles: [{ role: "root", db: "admin"}]
})

上記のコマンドの最初の行は、adminというデータベースを選択します。これは、すべての管理者の役割が格納されているデータベースです。 メソッドdb.createUser()を使用すると、実際のユーザーを作成し、そのユーザー名、パスワード、およびロールを定義できます。

このコマンドを実行すると、次のようになります。

Output
Successfully added user: { "user" : "admin_username", "roles" : [ { "role" : "root", "db" : "admin" } ] }

exitと入力して、MongoDBシェルを閉じることができます。

次に、MongoDBシェルに再度ログインしますが、今回は新しく作成されたadminユーザーでログインします。

mongo -u "admin_username" -p "admin_password" --authenticationDatabase "admin"

このコマンドは、MongoDBシェルを特定のユーザーとして開きます。ここで、-uフラグはユーザー名を指定し、-pフラグはそのユーザーのパスワードを指定します。 追加のフラグ--authenticationDatabaseは、adminとしてログインすることを指定します。

次に、新しいデータベースに切り替えてから、db.createUser()メソッドを使用して、このデータベースに変更を加える権限を持つ新しいユーザーを作成します。 強調表示されたセクションを独自の情報に置き換え、これらの資格情報を必ず書き留めてください。

MongoDBシェルで次のコマンドを実行します。

use database_name
db.createUser({
    user: "username",
    pwd: "password",
    roles: ["readWrite"]
})

これにより、次が返されます。

Output
Successfully added user: { "user" : "username", "roles" : ["readWrite"] }

データベースとユーザーを作成したら、このチュートリアルの後半でGraphQLサーバーから照会できるサンプルデータをこのデータベースに入力します。 これには、MongoDBWebサイトのbiosコレクションサンプルを使用できます。 次のコードスニペットのコマンドを実行することにより、このbiosコレクションデータセットの小さいバージョンをデータベースに挿入します。 強調表示されたセクションを独自の情報に置き換えることができますが、このチュートリアルでは、コレクションにbiosという名前を付けます。

db.bios.insertMany([
   {
       "_id" : 1,
       "name" : {
           "first" : "John",
           "last" : "Backus"
       },
       "birth" : ISODate("1924-12-03T05:00:00Z"),
       "death" : ISODate("2007-03-17T04:00:00Z"),
       "contribs" : [
           "Fortran",
           "ALGOL",
           "Backus-Naur Form",
           "FP"
       ],
       "awards" : [
           {
               "award" : "W.W. McDowell Award",
               "year" : 1967,
               "by" : "IEEE Computer Society"
           },
           {
               "award" : "National Medal of Science",
               "year" : 1975,
               "by" : "National Science Foundation"
           },
           {
               "award" : "Turing Award",
               "year" : 1977,
               "by" : "ACM"
           },
           {
               "award" : "Draper Prize",
               "year" : 1993,
               "by" : "National Academy of Engineering"
           }
       ]
   },
   {
       "_id" : ObjectId("51df07b094c6acd67e492f41"),
       "name" : {
           "first" : "John",
           "last" : "McCarthy"
       },
       "birth" : ISODate("1927-09-04T04:00:00Z"),
       "death" : ISODate("2011-12-24T05:00:00Z"),
       "contribs" : [
           "Lisp",
           "Artificial Intelligence",
           "ALGOL"
       ],
       "awards" : [
           {
               "award" : "Turing Award",
               "year" : 1971,
               "by" : "ACM"
           },
           {
               "award" : "Kyoto Prize",
               "year" : 1988,
               "by" : "Inamori Foundation"
           },
           {
               "award" : "National Medal of Science",
               "year" : 1990,
               "by" : "National Science Foundation"
           }
       ]
   }
]);

このコードブロックは、過去の成功した科学者に関する情報を含む複数のオブジェクトで構成される配列です。 これらのコマンドを実行してこのコレクションをデータベースに入力すると、データが追加されたことを示す次のメッセージが表示されます。

Output
{ "acknowledged" : true, "insertedIds" : [ 1, ObjectId("51df07b094c6acd67e492f41") ] }

成功メッセージが表示されたら、exitと入力してMongoDBシェルを閉じることができます。 次に、認証されたユーザーのみがデータにアクセスできるように、認証を有効にするようにMongoDBインストールを構成します。 MongoDBインストールの構成を編集するには、このインストールの設定を含むファイルを開きます。

sudo nano /etc/mongodb.conf

次のコードで強調表示されている行のコメントを解除して、認証を有効にします。

/etc/mongodb.conf
...
# Turn on/off security.  Off is currently the default
#noauth = true
auth = true
...

これらの変更をアクティブにするには、次のコマンドを実行してMongoDBを再起動します。

sudo systemctl restart mongodb

次のコマンドを実行して、データベースが再度実行されていることを確認します。

sudo systemctl status mongodb

これにより、次のような出力が得られます。

Output
● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago Docs: man:mongod(1) Main PID: 2388 (mongod) Tasks: 25 (limit: 1152) CGroup: /system.slice/mongodb.service └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

ユーザーが作成したデータベースに接続できることを確認するには、次のコマンドを使用して、認証されたユーザーとしてMongoDBシェルを開いてみてください。

mongo -u "username" -p "password" --authenticationDatabase "database_name"

これは以前と同じフラグを使用しますが、今回は--authenticationDatabaseが作成し、サンプルデータで埋められたデータベースに設定されます。

これで、 admin ユーザーと、サンプルデータを使用してデータベースへの読み取り/書き込みアクセス権を持つ別のユーザーが正常に追加されました。 また、データベースで認証が有効になっているため、データベースにアクセスするにはユーザー名とパスワードが必要です。 次のステップでは、チュートリアルの後半でこのデータベースに接続されるGraphQLサーバーを作成します。

ステップ2—GraphQLサーバーを作成する

データベースを構成してサンプルデータを入力したら、このデータをクエリして変更できるGraphQLサーバーを作成します。 これには、Node.jsで実行されるExpressexpress-graphqlを使用します。 ExpressはNode.jsHTTPサーバーをすばやく作成するための軽量フレームワークであり、express-graphqlは、GraphQLサーバーをすばやく構築できるようにするミドルウェアを提供します。

最初のステップは、マシンが最新であることを確認することです。

sudo apt update

次に、次のコマンドを実行して、サーバーにNode.jsをインストールします。 Node.jsと一緒に、Node.jsで実行されるJavaScriptのパッケージマネージャーであるnpmもインストールします。

sudo apt install nodejs npm

インストールプロセスを実行した後、インストールしたNode.jsのバージョンがv8.10.0以降であるかどうかを確認します。

node -v

これにより、次が返されます。

Output
v8.10.0

新しいJavaScriptプロジェクトを初期化するには、サーバー上でsudoユーザーとして次のコマンドを実行し、強調表示されたキーワードをプロジェクトの名前に置き換えます。

まず、サーバーのルートディレクトリに移動します。

cd

そこで、プロジェクトにちなんで名付けられた新しいディレクトリを作成します。

mkdir project_name

このディレクトリに移動します。

cd project_name 

最後に、次のコマンドを使用して新しいnpmパッケージを初期化します。

  1. sudo npm init -y

npm init -yを実行すると、次のpackage.jsonファイルが作成されたという成功メッセージが表示されます。

Output
Wrote to /home/username/project_name/package.json: { "name": "project_name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

注: -yフラグなしでnpm initを実行することもできます。その後、複数の質問に答えてプロジェクト名や作成者などを設定します。 詳細を入力するか、Enterキーを押して続行できます。

プロジェクトを初期化したので、GraphQLサーバーをセットアップするために必要なパッケージをインストールします。

sudo npm install --save express express-graphql graphql

index.jsという名前の新しいファイルを作成し、続いて次のコマンドを実行してこのファイルを開きます。

sudo nano index.js

次に、新しく作成したファイルに次のコードブロックを追加して、GraphQLサーバーをセットアップします。

index.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');

// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// Provide resolver functions for your schema fields
const resolvers = {
  hello: () => 'Hello world!'
};

const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

このコードブロックは、すべて重要ないくつかの部分で構成されています。 最初に、GraphQLAPIによって返されるデータのスキーマについて説明します。

index.js
...
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);
...

タイプQueryは、実行できるクエリと、結果を返す形式を定義します。 ご覧のとおり、定義されているクエリはhelloのみで、String形式でデータを返します。

次のセクションでは、リゾルバーを確立します。ここで、データはクエリ可能なスキーマと照合されます。

index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  hello: () => 'Hello world!'
};
...

これらのリゾルバーはスキーマに直接リンクされており、これらのスキーマに一致するデータを返します。

このコードブロックの最後の部分は、GraphQLサーバーを初期化し、Expressを使用してAPIエンドポイントを作成し、GraphQLエンドポイントが実行されているポートを記述します。

index.js
...
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

これらの行を追加したら、保存してindex.jsを終了します。

次に、GraphQLサーバーを実際に実行するには、Node.jsでファイルindex.jsを実行する必要があります。 これはコマンドラインから手動で実行できますが、これを実行するようにpackage.jsonファイルを設定するのが一般的な方法です。

package.jsonファイルを開きます。

sudo nano package.json

このファイルに次の強調表示された行を追加します。

package.json
{
  "name": "project_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

ファイルを保存して終了します。

GraphQLサーバーを起動するには、ターミナルで次のコマンドを実行します。

  1. npm start

これを実行すると、ターミナルプロンプトが消え、GraphQLサーバーが実行されていることを確認するメッセージが表示されます。

Output
🚀 Server ready at http://localhost:4000/graphql

ここで別のターミナルセッションを開くと、次のコマンドを実行してGraphQLサーバーが実行されているかどうかをテストできます。 これにより、GraphQLクエリを含む--dataフラグの後に、JSON本文を含むcurlPOSTリクエストがローカルエンドポイントに送信されます。

curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ hello }" }' http://localhost:4000/graphql

これにより、コードのGraphQLスキーマで記述されているとおりにクエリが実行され、リゾルバーで返されるデータと同じ予測可能なJSON形式でデータが返されます。

Output
{ "data": { "hello": "Hello world!" } }

注: Expressサーバーがクラッシュまたはスタックした場合は、サーバーで実行されているnodeプロセスを手動で強制終了する必要があります。 このようなプロセスをすべて強制終了するには、次のコマンドを実行できます。

killall node

その後、以下を実行してGraphQLサーバーを再起動できます。

npm start

このステップでは、サーバーでアクセスできるローカルエンドポイントで実行されているGraphQLサーバーの最初のバージョンを作成しました。 次に、リゾルバーをMongoDBデータベースに接続します。

ステップ3—MongoDBデータベースに接続する

GraphQLサーバーを順番に使用して、以前に構成してデータを入力したMongoDBデータベースとの接続をセットアップし、このデータに一致する新しいスキーマを作成できるようになりました。

GraphQLサーバーからMongoDBに接続できるようにするには、npmからMongoDBのJavaScriptパッケージをインストールします。

sudo npm install --save mongodb

これをインストールしたら、テキストエディタでindex.jsを開きます。

  1. sudo nano index.js

次に、インポートされた依存関係の直後に次の強調表示されたコードをindex.jsに追加し、強調表示された値にローカルMongoDBデータベースへの独自の接続の詳細を入力します。 usernamepassword、およびdatabase_nameは、このチュートリアルの最初のステップで作成したものです。

index.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const { MongoClient } = require('mongodb');

const context = () => MongoClient.connect('mongodb://username:[email protected]:27017/database_name', { useNewUrlParser: true }).then(client => client.db('database_name'));
...

これらの行は、ローカルMongoDBデータベースへの接続をcontextと呼ばれる関数に追加します。 このコンテキスト関数はすべてのリゾルバーで使用できるため、これを使用してデータベース接続を設定します。

次に、index.jsファイルで、次の強調表示された行を挿入して、GraphQLサーバーの初期化にコンテキスト関数を追加します。

index.js
...
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

これで、リゾルバーからこのコンテキスト関数を呼び出して、MongoDBデータベースから変数を読み取ることができます。 このチュートリアルの最初のステップを振り返ると、データベースに存在する値を確認できます。 ここから、このデータ構造に一致する新しいGraphQLスキーマを定義します。 定数schemaの前の値を、次の強調表示された行で上書きします。

index.js
...
// Construct a schema, using GrahQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
  }
  type Bio {
    name: Name,
    title: String,
    birth: String,
    death: String,
    awards: [Award]
  }
  type Name {
    first: String,
    last: String
  },
  type Award {
    award: String,
    year: Float,
    by: String
  }
`);
...

タイプQueryが変更され、新しいタイプBioのコレクションが返されるようになりました。 この新しいタイプは、他の2つの非スカラータイプNameAwardsを含むいくつかのタイプで構成されています。つまり、これらのタイプは、String[などの事前定義された形式と一致しません。 X176X]。 GraphQLスキーマの定義の詳細については、GraphQLのドキュメントを参照してください。

また、リゾルバーはデータベースからのデータをスキーマに結び付けるため、スキーマに変更を加えるときにリゾルバーのコードを更新します。 biosという名前の新しいリゾルバーを作成します。これは、スキーマにあるQueryと、データベース内のコレクションの名前に相当します。 この場合、db.collection('bios')のコレクションの名前はbiosですが、コレクションに別の名前を割り当てた場合は変更されることに注意してください。

次の強調表示された行をindex.jsに追加します。

index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) => context().then(db => db.collection('bios').find().toArray())
};
...

この関数は、MongoDBデータベースから変数を取得するために使用できるコンテキスト関数を使用します。 コードにこれらの変更を加えたら、index.jsを保存して終了します。

これらの変更をアクティブにするには、GraphQLサーバーを再起動する必要があります。 キーボードの組み合わせCTRL+ Cを使用して現在のプロセスを停止し、次のコマンドを実行してGraphQLサーバーを起動できます。

npm start

これで、更新されたスキーマを使用して、データベース内にあるデータをクエリできるようになりました。 スキーマを見ると、biosQueryがタイプBioを返すことがわかります。 このタイプは、タイプNameを返すこともできます。

データベース内のすべてのBIOSのすべての名前と名前を返すには、新しいターミナルウィンドウで次のリクエストをGraphQLサーバーに送信します。

 curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://localhost:4000/graphql

これも、スキーマの構造に一致するJSONオブジェクトを返します。

Output
{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}}]}}

Bioのタイプで説明されているタイプのいずれかでクエリを拡張することにより、BIOSからより多くの変数を簡単に取得できます。

また、idを指定して略歴を取得することもできます。 これを行うには、Queryタイプに別のタイプを追加し、リゾルバーを拡張する必要があります。 これを行うには、テキストエディタでindex.jsを開きます。

sudo nano index.js

次の強調表示されたコード行を追加します。

index.js
...
// Construct a schema, using GrahQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }

  ...

  // Provide resolver functions for your schema fields
  const resolvers = {
    bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),
    bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id }))
  };
  ...

ファイルを保存して終了します。

GraphQLサーバーを実行しているターミナルで、CTRL + Cを押して実行を停止し、次のコマンドを実行して再起動します。

  1. npm start

別のターミナルウィンドウで、次のGraphQLリクエストを実行します。

curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bio(id: 1) { name { first, last } } }" }' http://localhost:4000/graphql

これにより、id1に等しいバイオのエントリが返されます。

Output
{ "data": { "bio": { "name": { "first": "John", "last": "Backus" } } } }

データベースからデータをクエリできることだけがGraphQLの機能ではありません。 データベース内のデータを変更することもできます。 これを行うには、index.jsを開きます。

  1. sudo nano index.js

タイプQueryの横で、タイプMutationを使用することもできます。これにより、データベースを変更できます。 このタイプを使用するには、このタイプをスキーマに追加し、次の強調表示された行を挿入して入力タイプを作成します。

index.js
...
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }
  type Mutation {
    addBio(input: BioInput) : Bio
  }
  input BioInput {
    name: NameInput
    title: String
    birth: String
    death: String
  }
  input NameInput {
    first: String
    last: String
  }
...

これらの入力タイプは、リゾルバーでアクセスしてデータベースに新しいドキュメントを挿入するために使用できる入力として使用できる変数を定義します。 これを行うには、index.jsに次の行を追加します。

index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),
  bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id })),
  addBio: (args, context) => context().then(db => db.collection('bios').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0])
};
...

通常のクエリのリゾルバーと同様に、index.jsのリゾルバーから値を返す必要があります。 タイプBioが変異しているMutationの場合、変異したバイオの値を返します。

この時点で、index.jsファイルには次の行が含まれます。

index.js
iconst express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const { MongoClient } = require('mongodb');

const context = () => MongoClient.connect('mongodb://username:password@localhost:27017/database_name', { useNewUrlParser: true })
  .then(client => client.db('GraphQL_Test'));

// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }
  type Mutation {
    addBio(input: BioInput) : Bio
  }
  input BioInput {
    name: NameInput
    title: String
    birth: String
    death: String
  }
  input NameInput {
    first: String
    last: String
  }
  type Bio {
    name: Name,
    title: String,
    birth: String,
    death: String,
    awards: [Award]
  }
  type Name {
    first: String,
    last: String
  },
  type Award {
    award: String,
    year: Float,
    by: String
  }
`);

// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) =>context().then(db => db.collection('Sample_Data').find().toArray()),
  bio: (args, context) =>context().then(db => db.collection('Sample_Data').findOne({ _id: args.id })),
  addBio: (args, context) => context().then(db => db.collection('Sample_Data').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0])
};

const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

index.jsを保存して終了します。

新しいミューテーションが機能しているかどうかを確認するには、CTRL + cを押し、GraphQLサーバーを実行しているターミナルでnpm startを実行して、GraphQLサーバーを再起動し、別のターミナルを開きます。次のcurlリクエストを実行するセッション。 クエリのcurlリクエストと同様に、--dataフラグの本文がGraphQLサーバーに送信されます。 強調表示された部分がデータベースに追加されます。

curl -X POST -H "Content-Type: application/json" --data '{ "query": "mutation { addBio(input: { name: { first: \"test\", last: \"user\" } }) { name { first, last } } }" }' http://localhost:4000/graphql

これにより、次の結果が返されます。これは、データベースに新しいバイオを挿入したことを意味します。

Output
{ "data": { "addBio": { "name": { "first": "test", "last": "user" } } } }

このステップでは、MongoDBとGraphQLサーバーとの接続を作成し、GraphQLクエリを実行して、このデータベースからデータを取得および変更できるようにしました。 次に、このGraphQLサーバーをリモートアクセス用に公開します。

ステップ4—リモートアクセスを許可する

データベースとGraphQLサーバーをセットアップしたら、リモートアクセスを許可するようにGraphQLサーバーを構成できます。 このためには、前提条件のチュートリアル Ubuntu18.04にNginxをインストールする方法で設定したNginxを使用します。 このNginx構成は、/etc/nginx/sites-available/example.comファイルにあります。ここで、example.comは、前提条件のチュートリアルで追加したサーバー名です。

このファイルを開いて編集し、ドメイン名をexample.comに置き換えます。

sudo nano /etc/nginx/sites-available/example.com

このファイルには、ポート80をリッスンするサーバーブロックがあります。ここで、前提条件のチュートリアルでserver_nameの値をすでに設定しています。 このサーバーブロック内で、rootの値をGraphQLサーバーのコードを作成したディレクトリに変更し、index.jsをインデックスとして追加します。 また、ロケーションブロック内で、proxy_passを設定して、サーバーのIPまたはカスタムドメイン名を使用してGraphQLサーバーを参照できるようにします。

/etc/nginx/sites-available/example.com
server {
  listen 80;
  listen [::]:80;

  root /project_name;
  index index.js;

  server_name example.com;

  location / {
    proxy_pass http://localhost:4000/graphql;
  }
}

次のコマンドを実行して、この構成ファイルにNginx構文エラーがないことを確認します。

sudo nginx -t

次の出力が表示されます。

Output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

構成ファイルにエラーが見つからない場合は、Nginxを再起動します。

sudo systemctl restart nginx

これで、example.comを実行してサーバーのIPまたはカスタムドメイン名に置き換えることにより、任意のターミナルセッションタブからGraphQLサーバーにアクセスできるようになります。

curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://example.com

これにより、前の手順と同じJSONオブジェクトが返されます。これには、ミューテーションを使用して追加した可能性のある追加データが含まれます。

Output
{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}},{"name":{"first":"test","last":"user"}}]}}

GraphQLサーバーにリモートでアクセスできるようにしたので、ターミナルを閉じたとき、またはサーバーを再起動したときにGraphQLサーバーがダウンしないことを確認してください。 このようにして、リクエストを行うときはいつでも、GraphQLサーバーを介してMongoDBデータベースにアクセスできます。

これを行うには、npmパッケージ forever を使用します。これは、コマンドラインスクリプトを継続的に実行するか、障害が発生した場合に再起動することを保証するCLIツールです。

npmでforeverをインストールします。

sudo npm install forever -g

インストールが完了したら、package.jsonファイルに追加します。

package.json
{
  "name": "project_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "deploy": "forever start --minUptime 2000 --spinSleepTime 5 index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...

foreverを有効にしてGraphQLサーバーを起動するには、次のコマンドを実行します。

  1. npm run deploy

これにより、GraphQLサーバーを含むindex.jsファイルがforeverで開始され、障害が発生した場合に再起動するたびに、最小稼働時間2000ミリ秒と5ミリ秒で実行が継続されます。 これで、GraphQLサーバーはバックグラウンドで継続的に実行されるため、サーバーにリクエストを送信するときに、新しいタブを開く必要がなくなります。

これで、MongoDBを使用してデータを格納し、リモートサーバーからのアクセスを許可するように設定されたGraphQLサーバーが作成されました。 次のステップでは、GraphiQLプレイグラウンドを有効にします。これにより、GraphQLサーバーを簡単に検査できるようになります。

ステップ5—GraphiQLPlaygroundを有効にする

cURLリクエストをGraphQLサーバーに送信できることは素晴らしいことですが、特に開発中にGraphQLリクエストをすぐに実行できるユーザーインターフェイスを使用する方が高速です。 このために、パッケージexpress-graphqlでサポートされているインターフェースであるGraphiQLを使用できます。

GraphiQLを有効にするには、ファイルindex.jsを編集します。

  1. sudo nano index.js

次の強調表示された行を追加します。

index.js
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context,
  graphiql: true
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

ファイルを保存して終了します。

これらの変更を表示するには、次のコマンドを実行してforeverを停止してください。

forever stop index.js

次に、foreverを再度起動して、GraphQLサーバーの最新バージョンが実行されるようにします。

npm run deploy

URL http://example.comでブラウザを開き、example.comをドメイン名またはサーバーIPに置き換えます。 GraphQLリクエストを入力できるGraphiQLプレイグラウンドが表示されます。

The initial screen for the GraphiQL playground

このプレイグラウンドの左側で、GraphQLクエリとミューテーションを入力できますが、出力はプレイグラウンドの右側に表示されます。 これが機能しているかどうかをテストするには、左側に次のクエリを入力します。

query {
  bios {
    name {
      first
      last
    }
  }
}

これにより、同じ結果がプレイグラウンドの右側にJSON形式で出力されます。

The GraphiQL playground in action

これで、ターミナルとGraphiQLプレイグラウンドを使用してGraphQLリクエストを送信できます。

結論

このチュートリアルでは、MongoDBデータベースをセットアップし、サーバー用のGraphQL、Node.js、およびExpressを使用して、このデータベースからデータを取得および変更しました。 さらに、このサーバーへのリモートアクセスを許可するようにNginxを構成しました。 このGraphQLサーバーに直接リクエストを送信できるだけでなく、GraphiQLを視覚的なブラウザー内のGraphQLインターフェースとして使用することもできます。

GraphQLについて知りたい場合は、 NDC {London} でGraphQLに関する私のプレゼンテーションの記録を見るか、チュートリアルについてはWebサイトhowtographql.comにアクセスしてください。 GraphQLについて。 GraphQLが他のテクノロジーとどのように相互作用するかを調べるには、 Ubuntu 18.04 でPrismaサーバーを手動でセットアップする方法のチュートリアルを確認してください。MongoDBを使用してアプリケーションを構築する方法の詳細については、 Nest.js、MongoDB、およびVue.jsを使用したブログ。