スキーマ定義で出鼻をくじかれました。ついての勉強と備忘録を兼ねて入門記事を書こうと思います。完全に理解したと言えるようになることです。クエリ言語(QL)の一種です。クエリ言語って?ちょっと私のグーグル力に問題があるようで、以下にはあやふやな情報が含まれます。マサカリは随時受付中です。Language)は、データの問い合わせを行うための言語です。いうクエリ言語を発表したそうです。データの問い合わせを行うための言語です。クライアント-サーバー間のデータ問い合わせに特化した言語です。データ問い合わせを行うクエリ言語とは別に、データの構造を定義するスキーマ言語をもち、このスキーマ言語によってデータ構造の型定義を行うことができます。定義された型を用いることにより、型安全なデータ通信が可能になります。運用が簡単になるそうです。APIが真っ先に浮かぶ人は多いと思います。比較はこちらでも行われていますが、一応ここでも軽く触れておきましょう。リソースに対する操作をリクエストメソッドで規定していました。以下のようなデータ構造が存在するとします。以下のエンドポイントが必要になります。DELETE)この通り、リソースごとにエンドポイントが分割されており、その操作はリクエストメソッドという形で表現されます。これは以下のメリットがあります。アクセスする対象のリソースがわかりやすいリソースに対する操作もリクエストメソッドという形で表現されているためわかりやすい一方で、以下のようなデメリットもあります。種類)のリソースしか取得できない複数のリソースを取得したい場合は何度もリクエストを送信する必要があるリソースの種類が増えるのに伴い、エンドポイントも増えていくプロジェクトが肥大化するほど、上記のデメリットは無視できない大きさになっていきます。この問題を解消することができるのです。置き換えた場合に必要なエンドポイントは以下の通りです。POST)この通り、エンドポイントもリクエストメソッドも一本化されます。同じエンドポイントで、複数のリソースにアクセスすることができるようになるわけですね。問題なく動作するようです。使うことによるメリットは以下の通りです。つのままデメリットについてはまだよくわかっていないので、ここでは一旦横に置かせていただきます。騒がれる理由もわかってきました。仕様書を一部抜粋すると、こんなことが書かれています。GraphQLは、データ要件と相互作用を記述するための直感的で柔軟な構文とシステムを提供することにより、クライアントアプリケーションを構築するために設計されたクエリ言語です。GraphQLは、任意の計算が可能なプログラミング言語ではなく、この仕様で定義されている機能を持つアプリケーションサーバーのクエリに使用される言語です。GraphQLは、それを実装するアプリケーションサーバーに特定のプログラミング言語またはストレージシステムを強制しません。代わりに、アプリケーションサーバーはその機能を利用して、GraphQLがエンコードする統一言語、型システム、および哲学にそれらをマッピングします。これにより、製品開発に適した統合インターフェースと、ツール構築用の強力なプラットフォームが提供されます。データ問い合わせを行うための言語です。サーバー-データベース間の処理等に関しては関与しないのです。マイグレーションツールなどもありますが、それらは例外と見ていいでしょう。よって、本記事でもクライアント-サーバー間通信のみを想定した内容となります。リクエスト・レスポンスの流れについて確認していきます。参考資料は公式のこちら。リクエストの場合ユーザーの一覧を取得する場合について考えてみましょう。クエリは以下の文で表せるとします。リクエストの場合、上記を圧縮してクエリ文字列に突っ込むだけです。パラメータに入れるわけですね。ごっちゃになりそうです。形式で送信する方法です。当然ですが、ヘッダのContent-Typeとしてapplication/jsonを指定します。}それぞれのフィールドに関する説明は以下の通りです。クエリ形式で送信する方法もあります。Content-Typeにapplication/graphqlを指定すればいいようです。形式文字列で返されます。含まないべきであるそうです。仕様について確認していきます。基本的に公式ページの焼き増しです。この型定義を行うことができるのがスキーマ言語です。介した通信は、このスキーマ言語による型定義を元にしています。おいては、数値や文字などの実データを表す型として用いられるようです。おいてデフォルトで定義されている型を紹介します。特殊ですが、他の型はよく見る型ですね。上記以外にも、ユーザー独自に型を定義することができます。Dateという型を定義したい場合はこんな感じ。Dateただし、独自定義したスカラー型について、ユーザーは必要に応じてその変換処理を記述しなければなりません。上記Date型で言うのであれば、年月日までなのか、秒あるいはミリ秒までなのか、フォーマットはどうするかなどについて記述するべきでしょう。スキーマ定義範囲外です。ライブラリによって異なる記述になるので、利用するライブラリのドキュメントを確認してみましょう。gqlgenならこのページです。オブジェクトの型とフィールドここでは基本的な型の記述について確認していきましょう。型定義は、型名とフィールドからなります。}上記の例について確認してみましょう。ならないことを示している直感的でわかりやすいかと思います。簡単なオブジェクトならこれまでの知識で十分記述できそうですね。引数を持つフィールドフィールドには引数を定義することができます。以下の例を見てみましょう。}lengthフィールドに引数としてLengthUnit型のunitが指定されていますね。引数は必須および任意で指定することが可能です。不可を示す!を引数の型につけましょう。任意とした場合、引数にデフォルト値を指定することも可能です。上記の例はまさしくデフォルト値を指定されていますね。上記例だと、Float型の長さフィールドに、引数としてLengthUnitの単位を、デフォルトとしてMETER(メートル)として指定しています。スターシップの長さがメートル単位で取得できるのでしょう。型は特殊な意味を持ちます。おけるエンドポイントを示すことができるのです。具体的に見ていきましょう。サーバーに送り、データが取得できたとします。文が含まれていました。結果もそれぞれ取得できていますね。エンドポイントにheroおよびdroidが用意されていることを示しています。今回の例で言えば、例えば以下のような型定義が必要です。}Query型にheroフィールドおよびdroidフィールドが定義されていますね。ちなみに、heroでは引数が任意となっていますが、droid型では必須です。型に登録されたフィールドがエンドポイントとして登録されますが、型定義そのものは通常のオブジェクトと変わりません。覚えることが少なくてありがたいですね。行える処理が異なります。データの変更(POST、PUT)を意味します。型のみを定義すればいいわけですね。列挙型みんな大好き列挙型。説明の必要はないでしょう。}Episode型として指定されたフィールドには、NEWHOPE、EMPIRE、JEDIのいずれかしか入らないことを示すことができます。インターフェース様々なシステムで見られるインターフェースと似通ったものだそうです。以下のようなインターフェースがあるとします。フィールドを実装する必要があります。インターフェースを実装したHuman型とDroid型を見てみましょう。インターフェースで定義されていたフィールド以外については自由に実装することができます。Human型ではstarshipsとtotalCredits、Droid型ではprimaryFunctionが実装されていますね。同じインターフェースを実装している場合でも、型名が異なれば別個の型です。例として、以下のクエリ文と結果を見てみましょう。型の値を取得するクエリです。取得しようとしているわけです。型のすべてに含まれているとは限りません。そのため、エラーが発生しました。型の場合だったとき、一緒にprimaryFunctionの値を取得したい、といったこともあるでしょう。その場合、インラインフラグメントを使えば上手く取得することができます。基本的にはあんな感じです。これはSearchResult型を指定したフィールド等では、その実装としてHuman、Droid、Starshipのいずれかが入ることを意味します。型の結果を返すsearchクエリが存在する場合に、以下のような処理が行えます。}まず、__typenameは型名を表す文字列ですね。クライアントはこの文字列をもとに、取得できたデータの型を判断できます。先ほども出てきたインラインフラグメントですね。見ればそのままだと思いますが、型に応じて取得するフィールドを選択しています。型を実装しているため、以下のように書くことも可能です。入力型は、クエリの引数として用いられるフィールドの組み合わせを定義したものです。ReviewInput型を以下のように定義します。}typeではなくinputを使っているのがミソです。型を用いるCreateReviewForEpisodeクエリが存在する場合、以下のような処理が行えます。}実装を確認してはいませんが、これはエピソードごとの感想を登録するためのクエリだと推測することができると思います。型は感想を登録するために必要な情報を示している、と捉えることもできますね。このように、「ある操作を行うために必要な情報」について、入力型という形式で表現することができるわけです。入力型は通常の型と違い、フィールドに引数を設定することはできないので注意しましょう。クエリ言語ここからはクエリ言語についてです。クエリ言語を用いることにより、データの問い合わせやデータ変更依頼を行うことができます。フィールドごくごくシンプルなクエリの例として、以下のクエリ文を見てみましょう。型に登録されたフィールドを呼び出しています。持つフィールドのうち、取得したいフィールドを指定しているわけです。"R2-D2"が取得できています。以外にもappersInなどのフィールドを持っているはずです。ここでは指定したnameのみが返却されています。このように、必要なフィールドのみを選択的に取得することができるため、無駄なデータでクライアントのメモリを圧迫しにくくなるわけですね。型のフィールドとしてfriendsを持ち、かつfriendsはオブジェクトの配列だったとします。その場合、以下のような処理を行うこともできます。}フィールドがオブジェクトであれば、上記のように取得するフィールドを指定することができるわけです。型もオブジェクトであると考えれば、どんなクエリ文も取得するフィールドを指定しているだけと考えられますね。引数クエリ文には引数を渡すことができます。ある人間を取得するクエリは以下の通りです。クエリパラメータに入れる形になります。場合、ネストしたオブジェクトのフィールドそれぞれに引数を指定することができます。よって、取得するデータを柔軟に選択することができるようになるのです。上記の例でいえば、例えば身長をメートル表記からフィート表記に変えたい場合は以下のようになります。与える引数では役割が異なります。フィート変換処理のトリガーとなります。面白いところではないかと思います。エイリアスフィールドにはエイリアス(別名)をつけることができます。両者の区別がつきません。そこで、エイリアスをつけることで区別できるようになります。}上記の場合、通常はどちらもheroフィールドとなってしまいますが、エイリアスによってこれを回避しています。フラグメントフラグメントは、フィールド取得構成を使いまわすことのできる機能です。スキーマ言語の章でも、インラインフラグメントが出てきましたね。いうわけで、以下の例を見てください。}それぞれのフィールドとして..comparisonFieldsを指定しています。これは、取得するフィールドの指定をcomparisonFieldsフラグメントに委譲しています。型だった場合に取得するフィールドの指定を行っています。型が取得できるので、どちらもデータを取得できているわけですね。フラグメントには引数が利用できます。人までしか表示されていません。人しか友人がいないのでピッタリ表示されています。友達じゃないようですね。操作名は、発行するクエリに任意に指定することができる名称です。クエリ発行ごとに毎回指定できます。これまで例として記述されたクエリ文は、クエリ操作(query、mutation等)と操作名の指定を省略した記法になります。操作名を指定する場合、クエリ操作についても明記が必要です。}省略記法を用いる場合、操作名は不要になります。不要な操作名をあえて明記する理由は、サーバーのログ記録です。サーバーで記録することにより、不具合や問い合わせなどの際にログを追いかけることが容易になるのです。クエリ文と同時に変数の指定も送信することができます。定型の処理であれば、変数の値だけ変更してあげれば済みますね。例としては以下の通り。型を指定できる$episode変数が引数として存在します。JEDIを代入していますね。よって、複数の変数も代入することが可能です。いずれかでなければなりません。よって、複雑なオブジェクトを変数として指定したい場合は、入力型を利用する必要があります。何度か例示されていますが、初期値を設定することも可能です。上記の例で初期値をJEDIにしたい場合は以下の通り。}ディレクティブディレクティブ(Directives)とは、指令や命令といった意味があるそうです。ディレクティブを使うことで、取得するデータの構造を動的に変化させることができます。動的なデータ構造変化としてはフラグメントも該当すると思いますが、こちらは変数を与えることで動作します。フィールドを含むかどうか選択しています。フィールドを除く結果となりました。種類のみが定義されています。このディレクティブはライブラリやユーザー定義などで追加されることを想定した機能のようです。等のディレクティブが定義されています。リクエストではデータの取得のみを行います。リクエストメソッドを使い、明示的に示すべきとされています。この考え方を踏襲しています。データの変更を伴わない操作にはQueryを、データの変更を伴う操作にはMutationを利用するべきです。明示的に示したクエリ文の例です。}レビューを新規作成するクエリ文です。CreateReviewForEpisodeと、これがデータ変更を行うことを示していますね。この操作名はログとして保存されるべきです。データ変更を行うことも可能でしょう。おけるリクエストメソッドと同様に、規格に合わせることでよりわかりやすくバグの混入しにくいアプリケーションとすることが大事なのだと思います。ちなみに、変数として定義できるオブジェクトは入力型のみなので、ここで用いられているReviewInput型は入力型です。一度のクエリ文に複数仕込むことが可能です。その場合、上から順番に連続して実行されるようです。終わりに以上でこの記事は終わりです。細かいところは自分で作ってみなければ理解できないように感じます。各言語でライブラリが用意されているようなので、いろいろ試してみたいと思います。Docke...この記事についているタグGraphQL検索プロフィールjintz@jintzこいついつも何か始めてんな。