はじめに
前回の記事では、GraphQLについて軽く触れましたが、その時の理解は浅かったため、今回は深めることを目的として、GraphQLの構文をまとめてみました。
スキーマ
GraphQLのスキーマは、サーバーがクライアントに提供するデータ構造とAPIの操作を定義します。ここでは、スキーマ定義の基本的な構成要素を見ていきます。
Type
TypeはGraphQLの核となる部分です。データの形状を定義し、クエリやミューテーションで扱うオブジェクトの「設計図」となります。
type Book {
id: ID!
title: String!
author: String
}
上記のBook
タイプでは、id
とtitle
フィールドが非Nullであることが!
によって指定されています。これは、これらのフィールドがクエリの結果に必ず含まれるべきであることを意味します。一方で、author
フィールドには!
が付いていないため、このフィールドはnullを許容します。つまり、author
フィールドが値を持たない場合があることを示しています。
また、リストを扱う場合には、フィールドの型を[]
で囲みます。例えば、複数の著者を持つ書籍を表現したい場合、以下のように定義することができます。
type Book {
id: ID!
title: String!
authors: [String] # 著者のリスト
}
この定義では、authors
フィールドは文字列のリストを値として持つことができ、各著者の名前を含めることができます。リスト自体がnullを許容するかどうか、リストの各アイテムがnullを許容するかどうかは、!
の使用によって制御されます。
Field
Fieldは、Type内に定義される個々のデータ項目です。上のBook
タイプ例では、id
、title
、author
がFieldにあたります。
Interface
Interfaceは、異なるTypeが共有するFieldを定義するために使用されます。Interfaceを実装するTypeは、そのInterfaceのすべてのFieldを含む必要があります。
interface Character {
id: ID!
name: String!
}
type Human implements Character {
id: ID!
name: String!
totalCredits: Int
}
Union
Unionは、複数のTypeを一つのTypeとして扱うことができます。これにより、異なるTypeのオブジェクトを同じクエリで返すことができます。
union SearchResult = Book | Author
type Query {
search(query: String!): [SearchResult]
}
Scalar
Scalar型は、GraphQL内での基本的なデータの単位です。これらは具体的な単一の値を表し、複雑なオブジェクト型の構築ブロックとして機能します。GraphQLは以下の5つの組み込みScalar型を提供しています。
-
String
:UTF-8文字列。 -
Int
:符号付き32ビット整数。 -
Float
:符号付き倍精度浮動小数点数。 -
Boolean
:true
またはfalse
の論理値。 -
ID
:一意の識別子。String
と同じようにシリアライズされますが、IDとして特別扱いされ、オブジェクトを一意に識別するために使用されます。
これらのスカラー型は、単純なデータ構造の表現に使用されます。例えば、ユーザー名を表すフィールドはString
型、年齢を表すフィールドはInt
型になります。
カスタムScalar型を定義して使用することも可能です。これにより、日付や時間、バイト配列など、特定のフォーマットや制約を持つデータをより適切に扱うことができます。
例として、Date
型のScalarを定義することで、ISO 8601形式の日付文字列を受け入れ、返すことができます。
scalar Date
type Event {
id: ID!
title: String!
date: Date
}
このDate
型は、クライアントとサーバー間で日付データを正確にやり取りするためのカスタムScalar型の一例です。
Enum
Enumは、特定のフィールドが取りうる値を限定的なセットから選択するために使います。
enum BookGenre {
FICTION
NONFICTION
COMIC
}
Directive
Directiveは、GraphQLのクエリ実行の挙動を動的に変更するために使用されます。こ
GraphQL仕様には、組み込みのDirectiveがいくつかあり、さらにカスタムDirectiveを定義して、APIの挙動を拡張することができます。
組み込みDirective
-
@include(if: Boolean)
:このDirectiveは、指定された条件がtrue
の場合にのみフィールドを含めます。 -
@skip(if: Boolean)
:このDirectiveは、指定された条件がtrue
の場合にフィールドをスキップします。 -
@deprecated(reason: String)
:このDirectiveは、フィールドや列挙値が非推奨であることを示します。reason
引数に非推奨の理由を指定できます。
カスタムDirectiveを定義して、認証やアクセス制御など、独自のロジックをクエリに適用することも可能です。
directive @auth(requires: Role = ADMIN) on FIELD_DEFINITION
type User {
id: ID!
username: String!
email: String! @auth(requires: USER)
}
この例では、@auth
Directiveを使用してemail
フィールドに認証ロジックを適用しています。これにより、指定されたロールを持つユーザーのみがemail
フィールドにアクセスできます。
Description
Descriptionは、スキーマの各部分に対する説明を提供します。これは、ドキュメント生成に役立ちます。
"""
This is a book object representing a single book.
"""
type Book {
id: ID!
title: String!
author: String
}
Input Type
Input Typeは、特にミューテーションで使われる、入力データの形状を定義するために使います。
input CreateBookInput {
title: String!
author: String
}
このように、GraphQLのスキーマには、データ構造と操作を柔軟に定義するための多くの要素が含まれています。次に、実際にデータを取得するためのクエリについて詳しく見ていきます。
クエリ
GraphQLでは、データの取得(query
)、更新(mutation
)、サーバーサイドイベントの購読(subscription
)の三つの主要な操作があります。
Query
Query
Typeは、読み取り操作(データの取得)を定義するために使用されます。以下の例では、すべての本のリストを取得し、各本のid
とtitle
を要求しています。
type Query {
books: [Book]
}
query {
books {
id
title
}
}
Mutation
Mutation
Typeは、データの作成、更新、削除など、書き込み操作を定義するために使用されます。以下の例では、新しい本を追加するミューテーションを定義しています。
type Mutation {
createBook(input: CreateBookInput): Book
}
mutation {
createBook(input: {title: "GraphQL入門", author: "xxxxx"}) {
id
title
}
}
Subscription
Subscriptionは、GraphQLで定義された一種の操作であり、クライアントがサーバーからリアルタイムのデータ更新を購読するために使用されます。これは、WebSocketsなどの持続的な接続を通じて実装されることが多く、特にチャットアプリケーションやリアルタイムの通知システムで使用されます。
以下は、書籍の追加をリアルタイムで購読する簡単な例です。
type Subscription {
bookAdded: Book
}
subscription {
bookAdded {
id
title
author
}
}
この例では、新しい書籍が追加されるたびに、**bookAdded
**サブスクリプションを通じてその書籍の情報が購読者にプッシュされる構成になっています。これにより、アプリケーションはリアルタイムに新しい書籍の追加をユーザーに通知することができます。
Variables
クエリやミューテーション内で変数を使用することで、クエリの再利用性を高めることができます。変数は$
記号で始まります。
mutation CreateBook($input: CreateBookInput!) {
createBook(input: $input) {
id
title
}
}
Fragment
Fragment
は、複数のクエリやミューテーションで再利用可能なフィールドの集合を定義するために使用します。これにより、クエリの複雑さを減らすことができます。
fragment BookDetails on Book {
id
title
author
}
query {
books {
...BookDetails
}
}
まとめ
この記事を通じて、GraphQLの基本概念、スキーマ定義、タイプシステム、さらには操作タイプ(クエリ、ミューテーション、サブスクリプション)、変数の使用、フラグメントの利用など、GraphQLの中核となる構文について概観しました。これらの内容をまとめることで、GraphQLに関する理解が一層深まりました。