POSTD PRODUCED BY NIJIBOX

POSTD PRODUCED BY NIJIBOX

ニジボックスが運営する
エンジニアに向けた
キュレーションメディア

本記事は、原著者の許諾のもとに翻訳・掲載しております。

ワールドカップ2018の2次予選が始まった後で、私たちは、参加チームについての人々のあらゆる問いに答える 簡単な手段 を作りたいと思いました。

要約

ワールドカップ2018のために、グラフデータベースNeo4jを使ったGraphQL APIを作成しました。試してみたい人は、 ここをクリック してください。

グラフデータベースNeo4jを使ったGraphQL APIの作成

既に私たちは、 ワールドカップについての全てのデータのデータベース を作成して、人々がクエリに使えるようにしましたが、これを、Neo4jのクエリ言語、Cypherを知らない人でもアクセスできるようにしたいと思いました。

GraphQLに助けてもらおう

GraphQLの話をする前に、まず、私たちが作ったNeo4jグラフモデルを見てください。

グラフの中央に WorldCup ノードがあって、その周りにモデルの他のパーツが散らばっています。各トーナメントについて1つのWorldCupノードがあります。

ホスト国である Country(国) が、 HOSTED_BY(開催) という関係でWorldCupに結び付いています。WorldCupノードには、複数の Match(試合) が属していて、それぞれの Countryは 、複数の Player(選手) からなる Squad(チーム) を指名し、これが、ワールドカップトーナメントで選手たちを表します。

選手は、チームが参加する試合のそれぞれについて、スタメン(STARTED)かベンチ入り(SUBSTITUTE)のどちらかとして Appearance(出場) ノードに結び付けられます。 Goal(ゴール) が決まると、AppearanceノードがGoalノードに結ばれます(SCORED GOAL)。

GRANDstackスターターキット

Neo4jの説明はこれで十分なので、GraphQLに戻ります。

GRANDstackは、 GraphQLReactApolloNeo4j Database を、簡単にAPIとアプリを作るための使いやすいバンドルにまとめたものです。GRANDstackはGraphQLのスキーマを使ってGraphQLのクエリを 単一の Neo4jクエリに自動的にトランスパイルし、注釈付きスキーマから、全てのクエリ、ミューテーション、フィールドを自動生成することができます。


GRANDstackのロゴ

GRANDstack.ioスターターキット を使って、既に出来上がっているNeo4jデータベースに重ねてGraphQL APIを作りました。

このGraphQL APIは、バックエンド api とフロントエンド ui の2つの部分からなります。バックエンドはGraphQL APIと、さらにGraphQL Playgroundをサービスします。GraphQL Playgroundは、GraphQLクエリのためのとても素敵なブラウザ兼エディタで、データスキーマ、ドキュメント、オートコンプリートを備えています。

私たちはそれを自分たちのレポジトリにforkしてから、 ブランチ worldcup へマージして、使えるようにしました。

最初のステップは、 GraphQLスキーマ の作成です。私たちの思いついたスキーマは下記のとおりで、これは先ほど見たグラフモデルの中のものに密接に対応しています。
最小限のスキーマは次のとおりです:

GraphQLスキーマの最小限の部分

これを、GRANDstack専用のNeo4jエクステンションをいくつか使ってかなり拡張し、代替マッピングなどを加えました。


― GRANDstackのフルスタックアプリのためのシンプルなスターターキット

スキーマを定義し終わってから、.envファイルを更新して、Neo4jクラウド(https://neo4j.com/cloud/)にホスティングされた私たちのデータベースを指すようにしました。

NEO4J_URI=bolt://c27d992b.databases.neo4j.io
NEO4J_USER=worldcup
NEO4J_PASSWORD=worldcup

これをローカルで動作させるには、 yarn && yarn start を実行します。すると、Playgroundが http://localhost:4000 でローンチされ、クエリを使って遊ぶことができます。

世界でベストの選手は誰か、というクエリを書くこともできます。


GraphQL Playgroundの画面

もちろん、その選手について、もっと詳しいことを尋ねることもできます。


メッシの詳細についてのクエリの結果

zeit.nowへのデプロイ

これで、デプロイの準備ができました。Node.jsアプリをホスティングしているところなら、どこにでも自分たちのサービスをデプロイできますが、@Will.Lyonに Zeit Now を勧められました。これは、アプリのホスティングに簡単に使える素晴らしいサービスで、小さなプロジェクト向けの使いやすい無料プランがあります。

このサービスをインストールしてから、デプロイ先のディレクトリでnowコマンドを実行するだけです。不変のURLにするには、固定の名前でプロジェクトのエイリアスを作成できます。

このGraphQLサーバは https://worldcup-2018.now.sh/ にデプロイされ、使う準備ができました。このデータセットにかけられるクエリのタイプを見てみましょう。

ポルトガル対モロッコ

この記事を書いている時点で、 ポルトガルモロッコ と対戦しています。このGraphQLクエリを先ほど定義したプレイグラウンドで実行すると、最新のスコアをチェックできます。


ポルトガル対モロッコの結果

現在ポルトガルが1-0でリードしており、得点者は当然ながらクリスティアーノ・ロナウドでした。

ロナウドってどんな選手?

クリスティアーノについて詳しく知りたいなら、選手についてのクエリも可能です。例えば、下記のクエリでは、彼の生年月日や、これまでのワールドカップでのゴールの回数、さらには、今回のゴールの回数も問い合わせることができます。

彼はワールドカップ2018で4つのゴールを獲得し、通算で7つになりました。つまり、今回のトーナメントで獲得したゴールの数が、前回までのトーナメントでのゴールの合計を超えたことになります。

1990年のドイツのスコア

ドイツは今回のワールドカップでは好調なスタートを切ったとは言えませんが、1990年ワールドカップ決勝のスコアを懐かしむクエリを書いてみましょう。

1966年の敗北

同僚のマークがどうしても見たいそうなので、1996年の結果のクエリも書いてみました。

データを最新に維持する

このデータベースは試合が行われている間、数分ごとにLambdaのジョブで更新されるので、いつクエリを行ってもデータは適切に最新の状態になっているはずです。

ReactのUI

フロントエンド ui は、基本的には単なるReactアプリで、Apollo Clientを使って私たちのAPIにクエリをかけ、結果をコンポーネントにレンダリングします。

今のReactコードは、ご覧のとおり、とても醜悪で悲惨です。これを課題として残しておきますので、ぜひ、 World Cup GraphQL API を使って、美しいウェブアプリやモバイルアプリを作ってください。


私の(醜悪な)ワールドカップ画面

もちろん、VueやAngularなど、あなたの好きなUIフレームワークを使っても構いません。

アプリは、 .env ファイルの中のURLに接続します。私たちは、このファイルにローカルの http://localhost:4000 または自分たちのnow.sh URIを書き込みました。

REACT_APP_GRAPHQL_URI=https://worldcup-2018.now.sh/

ここでも、ただ1つの now コマンドが、私たちのUIもデプロイします。私たちのケースには必要ありませんが、Zeitでは現在、secret credentialsがサポートされています。

GRANDstackハッカソン

幸いなことに、 GRANDstackハッカソン優れたアイデアの収集を今も続けていて 、とても素敵な報償も用意されています。

データとモデルの取りまとめに尽力してくれた、同僚の Mark Needham に感謝します。