GraphQLをNode.jsとexpressでためしてみる

はじめに

最近GraphQLに興味が湧いています。ちょっと試してみたくなったので、チュートリアルをやってみました。思いのほか簡単に試せたので紹介したいと思います。10分くらいでできますので、ぜひやってみてください。

参照したのはこちらのチュートリアルです。

Creating A GraphQL Server With Node.js And Express

GraphQLとは

GraphQLは、一言で言えば「必要なデータを過不足なく、一度に取りだす」ことのできるクエリ言語です。

http://graphql.org/

GitHubをはじめ多くのサービスでサポートが表明されています。流行っているようでいて、でもそれほどでもないような。しかし微妙に注目されているという立ち位置でしょうか。

やってみる

node.jsとexpressでGraphQLサーバを作ってみます。

環境

  • macOS 10.12.6 Sierra
  • express 4.16.3
  • express-graphql 0.6.12
  • graphql 0.13.2

準備

node.jsを使いますので、もし手元にない場合にはインストールしておきます。

$ brew install node

プロジェクトの作成

プロジェクトフォルダを作成して、npm initしておきます。

$ mkdir gql-server
$ cd gql-server/
$ npm init

パッケージをインストール

npmで必要なパッケージをインストールします。

  • graphql
  • express
  • express-graphql
$ npm install graphql express express-graphql -save

最初のサーバ

下の内容でserver.jsを作ります。messageというクエリに対して、Hello World!を返すサーバです。

var express = require('express');
var express_graphql = require('express-graphql');
var { buildSchema } = require('graphql');
// GraphQL schema
var schema = buildSchema(`
 type Query {
 message: String
 }
`);
// Root resolver
var root = {
 message: () => 'Hello World!'
};
// Create an express server and a GraphQL endpoint
var app = express();
app.use('/graphql', express_graphql({
 schema: schema,
 rootValue: root,
 graphiql: true
}));
app.listen(4000, () => console.log('Express GraphQL Server Now Running On localhost:4000/graphql'));

実行してみます。

$ node server.js
Express GraphQL Server Now Running On localhost:4000/graphql

ブラウザで、http://localhost:4000/graphql にアクセスしてみると、クエリができるGraphiQLの画面が出てきます。

クエリしてみる

最初のクエリを送ってみます。左側のペーンに下のクエリを貼り付け、実行ボタンをクリックします。

{
  message
}

そうすると、右側に結果が表示されました。

ちゃんと"Hello World!"できました!

今回は単純なパラメータの無い単純なクエリでしたが、パラメータを付ける場合は、左下をクリックするとフィールドが出てきます。

パラメータを受け取るGraphQLサーバ

もうちょっと中身のある、パラメータを受け取って、結果を返すサーバです。coursecoursesという二つのクエリが定義されています。データは埋め込みとなっている簡単なものです。

下の内容の、server2.jsを作成します。

var express = require('express');
var express_graphql = require('express-graphql');
var { buildSchema } = require('graphql');
// GraphQL schema
var schema = buildSchema(`
 type Query {
 course(id: Int!): Course
 courses(topic: String): [Course]
 },
 type Course {
 id: Int
 title: String
 author: String
 description: String
 topic: String
 url: String
 }
`);
var coursesData = [
 {
 id: 1,
 title: 'The Complete Node.js Developer Course',
 author: 'Andrew Mead, Rob Percival',
 description: 'Learn Node.js by building real-world applications with Node, Express, MongoDB, Mocha, and more!',
 topic: 'Node.js',
 url: 'https://codingthesmartway.com/courses/nodejs/'
 },
 {
 id: 2,
 title: 'Node.js, Express & MongoDB Dev to Deployment',
 author: 'Brad Traversy',
 description: 'Learn by example building & deploying real-world Node.js applications from absolute scratch',
 topic: 'Node.js',
 url: 'https://codingthesmartway.com/courses/nodejs-express-mongodb/'
 },
 {
 id: 3,
 title: 'JavaScript: Understanding The Weird Parts',
 author: 'Anthony Alicea',
 description: 'An advanced JavaScript course for everyone! Scope, closures, prototypes, this, build your own framework, and more.',
 topic: 'JavaScript',
 url: 'https://codingthesmartway.com/courses/understand-javascript/'
 }
]
var getCourse = function(args) { 
 var id = args.id;
 return coursesData.filter(course => {
   return course.id == id;
 })[0];
}
var getCourses = function(args) {
 if (args.topic) {
  var topic = args.topic;
  return coursesData.filter(course = course.topic === topic);
 } else {
  return coursesData;
 }
}
var root = {
 course: getCourse,
 courses: getCourses
};
// Create an express server and a GraphQL endpoint
var app = express();
app.use('/graphql', express_graphql({
 schema: schema,
 rootValue: root,
 graphiql: true
}));
app.listen(4000, () => console.log('Express GraphQL Server Now Running On localhost:4000/graphql'));

実行してみます。

$ node server2.js 
Express GraphQL Server Now Running On localhost:4000/graphql

クエリを送ってみる

courseを一つ取り出すクエリを送ってみます。パラメータとして整数$couseIDを付けて、courseからtitle, author, descrption, topic, urlを取り出します。

左上にクエリを貼り付けます。

query getSingleCourse($courseID: Int!) {
 course(id: $courseID) {
  title
  author
  description
  topic
  url
 }
}

パラメータとして、左下に貼り付けます。

{ 
 "courseID":1
}

そして実行してみます。



ちゃんと結果が得られました!

違うクエリを試す

もう一つcoursesというクエリが定義されていますので、こちらも試してみます。topicが一致するものを複数返すというクエリです。今度はtitleとurlだけを返すようにしてみます。

query getCourses($topic: String!) {
 courses(topic: $topic) {
  title
  url
 }
}

パラメータを、左下に貼り付けます。

{ 
 "topic":"Node.js"
}

topicが"Node.js"となっているcourseが二つ返答されました。

更新できるGraphQLサーバ

問い合わせだけじゃなく、更新も試してみます。

さきほどのserver2.jsをコピーして、更新用のクエリを追加して、スキーマを置き換えます。

...
// GraphQL schema
var schema = buildSchema(`
 type Query {
 course(id: Int!): Course
 courses(topic: String): [Course]
 },
 type Mutation {
 updateCourseTopic(id: Int!, topic: String!): Course
 }
 type Course {
 id: Int
 title: String
 author: String
 description: String
 topic: String
 url: String
 }
`);
...

 

そして、下記のデータ更新クエリの実装を追加します。

...
var updateCourseTopic = function({id, topic}) {
 coursesData.map(course => {
 if (course.id === id) {
 course.topic = topic;
 return course;
 }
 });
 return coursesData.filter(course => course.id === id) [0];
}
var root = {
 course: getCourse,
 courses: getCourses,
 updateCourseTopic: updateCourseTopic
};
...

先ほどと同様に、サーバを起動します。

$ node server3.js 

更新クエリを送る

更新クエリupdateCourseTopicを送ってみます。パラメータで$id$topicを受け取り、fragmentで返すカラムを定義しています。

mutation updateCourseTopic($id: Int!, $topic: String!) {
  updateCourseTopic(id: $id, topic: $topic) {
    ... courseFields 
  }
}
fragment courseFields on Course {
 title
 author
 description
 topic
 url
}

パラメータです。id=1のtopicをJavaScriptに更新するという意味になります。

{
 "id": 1,
 "topic": "JavaScript"
}

クエリを実行してみると、ちゃんと更新した結果が返されました。

こんな感じで、クエリを追加したりしていけば、いろいろ試せそうです。

GraphiQL

express-graphqlに入っているGraphiQLという画面ですが、結構便利です。

ヒストリ

クエリのヒストリが出せて、編集しての再クエリが簡単にできます。

スキーマ

<Docsというリンクをクリックすると、GraphQLサーバのスキーマを参照することができます。

スキーマからコンプリーションも機能するので、便利です。

まとめ

Node.jsとexpressを使ったGraphQLサーバを試してみました。単純なサーバを立てて、簡単なクエリを試すのが、とても簡単にできました。

GraphiQLという画面で、クエリをいろいろ試せるのがいい感じです。ぜひ試してみてください。

DBとつないだり、権限管理してみたり、サーバレスで動かしたりしてみたいですね!

参考