はじめに
GraphQL Meshとは複数のバックエンドサービスを束ねるGraphQLゲートウェイを構築するためのフレームワークです。GraphQL Mesh自体についての詳細は、数多くの記事が世の中にあるため省きます。
今回はGraphQL Meshを利用して、MySQLをラップしてGraphQLで扱う方法について試していきます。GraphQL Meshを経由して扱うことで、スキーマを自前で用意せずに既に存在するDB情報から自動で生成して取り扱うことができるようになります。
ローカルで動かすまでの手順
今回はローカルのdevサーバーとしてGraphQL Meshを立てて、任意のMySQLのDBを操作するところまで試します。
準備しておくもの
- ローカルからアクセス可能なMySQLサーバー
- 検証用に適当なデータベースとテーブルを作っておく
- 今回はMySQL8.0を使っています
必要なパッケージのインストール
適当なディレクトリを作成し、その中に必要なパッケージをインストールします。
$ yarn add graphql @graphql-mesh/cli @graphql-mesh/mysql
.meshrc.ymlの作成
設定ファイルであるところの.meshrc.yml
を先程作ったディレクトリに追加して、内容を記述します。
sources:
- name: MySQL #任意のName
handler:
mysql:
host: localhost #MySQLサーバーのホスト
port: 3306 #ポート番号
user: root #ユーザー名 今回は検証用にrootでアクセスする
password: password #パスワード
database: MyDatabase # 作成したDB名
handler
をmysql
とすることで、Meshが自動的にDBの定義を読み取り、DBの操作に必要なGraphQLのスキーマを用意してくれるようになります。この他にも、host
やport
等と並ぶところにtables
やtableFields
を配列で記述することでアクセスできる領域をホワイトリスト形式で制限することができます。(残念ながら、読み取りのみ
や削除禁止
などの細かい制限はできないようです。)
devサーバーの起動
GraphQL Meshのdevサーバーを起動します。
$ yarn mesh dev
実行すると、自動的にlocalhost:4000
がブラウザで開かれ、GraphiQL
が立ち上がります。
失敗する場合は、必要なパッケージがインストールされているか
MySQLサーバーと疎通できているか
あたりを確認してください。
スキーマの確認
Docsを見ると、接続したDBを操作するためのスキーマがいくつか用意されているのが確認できると思います。
序文でも書いた通り、これらのスキーマはDB接続時に自動的に生成されるため、GraphQL Mesh側で管理する必要がありません。
Queryを実行してみる
画面中央のフィールドにQueryを記述し、行を取得してみます。
余談ですが、公式ドキュメントではget${テーブル名}
のような定義がされるように例が書かれているものの、実際はテーブル名だけの定義になっているようです。
{
test_table(
limit: 1,
where: {
id: "1"
}
) {
id
name
comment
}
}
MySQLのようにlimit
やwhere
が見られますが、まさにMySQLのクエリと同じ動きをしてくれます。公式ドキュメントによると、これらのGraphQLのスキーマは適切なMySQLのクエリに変換されて、DBに送信されます。上記の例でいうと、下記のクエリに変換されるようです。
SELECT id, name, comment FROM test_table
WHERE id = '1'
LIMIT 1;
基本的には用意されたスキーマに従って記述するだけで、MySQLのクエリと同じように行の取得が可能です。CodeSandboxにあげられているexampleを見る限り、JOIN句と同等の取得にも対応しているため、ある程度複雑な内容であっても対応できそうです。
Mutationを実行してみる
MySQLで言うところのUPDATE
INSERT
DELETE
はMutationで行います。
テーブルごとにそれぞれの命令に相当するスキーマが定義されているため、必要に応じたスキーマを使う必要があります。
今回はUPDATE
を実行します。
mutation update {
update_test_table(test_table: {
name: "updated",
comment: "変更します"
},
where: {
id: "1"
}) {
name
comment
}
}
前段のQueryで再取得すると、内容の変更が確認できました。
Mutationに関しても、Queryと同様に用意されたスキーマに従って記述するだけでDBの操作を行うことができます。
INSERT
とDELETE
も下記のように記述すれば実行できました。
mutation insert {
insert_test_table(test_table: {
id: "2",
name: "second",
comment: "テスト"
}) {
id
name
comment
}
}
mutation delete {
delete_test_table(
where: {
id: "2"
})
}
懸念点
現時点では、いくつかの懸念点があると個人的に感じました。
- 単体では、認可の仕組みを持てない。
- 参照できるテーブルとカラム以外に関しては、これ単体では制御できないので、パブリックな場で公開するようなサービスで使う場合は誰に触られても良いような領域でしか使わない、もしくは別でそのあたりを制御する仕組みを用意する必要がありそうです。
- INSERTがAUTO_INCREMENTに対応していない。
- idを
AUTO_INCREMENT
かつNOT NULL
にするというのはかなりよくあるケースだと思うのですが、insert
のMutationを実行時にidが無指定だとエラーになって怒られてしまいます。ここは中々不便。
- idを
- トランザクションが使えない。
- 構造的に当然といえば当然ですが、トランザクションが使えないので複雑な更新処理などは難しいです。
まとめ
GraphQL Mesh経由でMySQLを操作する方法のご紹介でした。(MySQLをGraphQLでラップしたいというのも、それなりにニッチな需要な気がしますが、)実装とスキーマの管理不要で簡単に導入できるので、狭い領域や個人用であれば選択肢に挙げられる便利なツールだと思います。