Ubuntu18.04でNode.jsとMongoDBを使用してGraphQLサーバーを構築およびデプロイする方法
著者は、ウィキメディア財団を選択して、 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サーバーとすばやくインターフェースします。
前提条件
このガイドを開始する前に、次のものが必要です。
-
Ubuntu18.04初期サーバーセットアップガイドに従ってセットアップされたUbuntu18.04サーバー。sudo非rootユーザーとファイアウォールが含まれます。
-
Ubuntu 18.04で実行されているMongoDBのインストール。これは、チュートリアル Ubuntu18.04にMongoDBをインストールする方法に従ってセットアップできます。
-
Ubuntu 18.04 にNginxをインストールする方法(ステップ4 –サーバーブロックの設定を含む)に示されているように、Nginxがインストールされています。
-
GraphQLサーバーへのリモートアクセスを許可するには、完全修飾ドメイン名(FQDN)とサーバーIPを指すAレコードが必要です。 これについて詳しくは、 DNSの用語、コンポーネント、概念の概要、またはDigitalOceanアカウントをお持ちの場合はドメインとDNSのドキュメントをご覧ください。
-
シリーズJavaScriptでコーディングする方法から得られるJavaScriptに精通していること。
ステップ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()
を使用すると、実際のユーザーを作成し、そのユーザー名、パスワード、およびロールを定義できます。
このコマンドを実行すると、次のようになります。
OutputSuccessfully 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"]
})
これにより、次が返されます。
OutputSuccessfully 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
次のコードで強調表示されている行のコメントを解除して、認証を有効にします。
...
# 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で実行されるExpressとexpress-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
これにより、次が返されます。
Outputv8.10.0
新しいJavaScriptプロジェクトを初期化するには、サーバー上でsudo
ユーザーとして次のコマンドを実行し、強調表示されたキーワードをプロジェクトの名前に置き換えます。
まず、サーバーのルートディレクトリに移動します。
cd
そこで、プロジェクトにちなんで名付けられた新しいディレクトリを作成します。
mkdir project_name
このディレクトリに移動します。
cd project_name
最後に、次のコマンドを使用して新しいnpmパッケージを初期化します。
- sudo npm init -y
npm init -y
を実行すると、次のpackage.json
ファイルが作成されたという成功メッセージが表示されます。
OutputWrote 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サーバーをセットアップします。
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によって返されるデータのスキーマについて説明します。
...
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
type Query {
hello: String
}
`);
...
タイプQuery
は、実行できるクエリと、結果を返す形式を定義します。 ご覧のとおり、定義されているクエリはhello
のみで、String
形式でデータを返します。
次のセクションでは、リゾルバーを確立します。ここで、データはクエリ可能なスキーマと照合されます。
...
// Provide resolver functions for your schema fields
const resolvers = {
hello: () => 'Hello world!'
};
...
これらのリゾルバーはスキーマに直接リンクされており、これらのスキーマに一致するデータを返します。
このコードブロックの最後の部分は、GraphQLサーバーを初期化し、Expressを使用してAPIエンドポイントを作成し、GraphQLエンドポイントが実行されているポートを記述します。
...
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
このファイルに次の強調表示された行を追加します。
{
"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サーバーを起動するには、ターミナルで次のコマンドを実行します。
- npm start
これを実行すると、ターミナルプロンプトが消え、GraphQLサーバーが実行されていることを確認するメッセージが表示されます。
Output🚀 Server ready at http://localhost:4000/graphql
ここで別のターミナルセッションを開くと、次のコマンドを実行してGraphQLサーバーが実行されているかどうかをテストできます。 これにより、GraphQLクエリを含む--data
フラグの後に、JSON本文を含むcurl
POST
リクエストがローカルエンドポイントに送信されます。
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
を開きます。
- sudo nano index.js
次に、インポートされた依存関係の直後に次の強調表示されたコードをindex.js
に追加し、強調表示された値にローカルMongoDBデータベースへの独自の接続の詳細を入力します。 username
、password
、およびdatabase_name
は、このチュートリアルの最初のステップで作成したものです。
const 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('database_name'));
...
これらの行は、ローカルMongoDBデータベースへの接続をcontextと呼ばれる関数に追加します。 このコンテキスト関数はすべてのリゾルバーで使用できるため、これを使用してデータベース接続を設定します。
次に、index.js
ファイルで、次の強調表示された行を挿入して、GraphQLサーバーの初期化にコンテキスト関数を追加します。
...
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
の前の値を、次の強調表示された行で上書きします。
...
// 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つの非スカラータイプName
とAwards
を含むいくつかのタイプで構成されています。つまり、これらのタイプは、String
や
また、リゾルバーはデータベースからのデータをスキーマに結び付けるため、スキーマに変更を加えるときにリゾルバーのコードを更新します。 bios
という名前の新しいリゾルバーを作成します。これは、スキーマにあるQuery
と、データベース内のコレクションの名前に相当します。 この場合、db.collection('bios')
のコレクションの名前はbios
ですが、コレクションに別の名前を割り当てた場合は変更されることに注意してください。
次の強調表示された行を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
これで、更新されたスキーマを使用して、データベース内にあるデータをクエリできるようになりました。 スキーマを見ると、bios
のQuery
がタイプ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
次の強調表示されたコード行を追加します。
...
// 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
を押して実行を停止し、次のコマンドを実行して再起動します。
- npm start
別のターミナルウィンドウで、次のGraphQLリクエストを実行します。
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bio(id: 1) { name { first, last } } }" }' http://localhost:4000/graphql
これにより、id
が1
に等しいバイオのエントリが返されます。
Output{ "data": { "bio": { "name": { "first": "John", "last": "Backus" } } } }
データベースからデータをクエリできることだけがGraphQLの機能ではありません。 データベース内のデータを変更することもできます。 これを行うには、index.js
を開きます。
- sudo nano index.js
タイプQuery
の横で、タイプMutation
を使用することもできます。これにより、データベースを変更できます。 このタイプを使用するには、このタイプをスキーマに追加し、次の強調表示された行を挿入して入力タイプを作成します。
...
// 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
に次の行を追加します。
...
// 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
ファイルには次の行が含まれます。
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サーバーを参照できるようにします。
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
次の出力が表示されます。
Outputnginx: 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
ファイルに追加します。
{
"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サーバーを起動するには、次のコマンドを実行します。
- 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
を編集します。
- sudo nano 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プレイグラウンドが表示されます。
このプレイグラウンドの左側で、GraphQLクエリとミューテーションを入力できますが、出力はプレイグラウンドの右側に表示されます。 これが機能しているかどうかをテストするには、左側に次のクエリを入力します。
query {
bios {
name {
first
last
}
}
}
これにより、同じ結果がプレイグラウンドの右側にJSON形式で出力されます。
これで、ターミナルと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を使用したブログ。