GraphQLのスキーマと型定義

## GraphQLのスキーマとは
GraphQL APIの仕様を表現するものです。スキーマ定義言語（SDL(Schema Definition Language)）を使って表現します。GraphQL APIを構築するにあたり、FW、言語に依存せずにSDLで表現できます。
以下、SDLでのスキーマ定義の例です。

```schema.graphqls
type Book {
    id: ID!
    name: String
    pageCount: Int
    author: Author
}

type Author {
    id: ID!
    firstName: String
    lastName: String
}
```

GraphQLをJavaで実装する場合、以下のようにJavaコードでの定義も可能です（Java以外の言語でもその言語で定義することが可能です）。
https://www.graphql-java.com/documentation/master/schema/

## GraphQLの型とは
上記のようにSDLを使ってスキーマ定義する際に、重要となってくる概念に型というものがあります。GraphQLの型は他の言語同様、String、int、booleanといったようにデータの種類を識別するためのものです。GraphQLには大きく分けてスカラー型とオブジェクト型が存在します。それぞれ以下に詳細を記載します。

#### スカラー型
GraphQLには以下の5つのスカラー型が存在します。これら5つを総称してスカラー型と呼びます。

* String（文字列型）
* Int（整数型）
* Float（浮動小数点型）
* Boolean（論理型）
* ID（ID型）

IntとFloatはJSONではnumberで表現されます。StringとIDはJSONではstringで表現されます。Booleanはそのままです。また、ID型の実態は文字列（String）ですが、GraphQLの仕様上ユニークでなければならない点でString型と区別されています。

#### オブジェクト型
1つ以上のスキーマで定義されているフィールドの集合をオブジェクト型といいます。JSONのように入れ子にすることが可能です。

上記で挙げたSDLサンプルを使ってまとめると以下のようになります。

```schema.graphqls
type Book {
    id: ID!　←スカラー型（ID）
    name: String　←スカラー型（String）
    pageCount: Int　←スカラー型（Int）
    author: Author　←オブジェクト型（下記Authorスキーマにあるようにフィールドの集合）
}

type Author {
    id: ID!　←スカラー型（ID）
    firstName: String　←スカラー型（String）
    lastName: String　←スカラー型（String）
}
```

#### 列挙型（Enum）の定義
列挙型（Enum）も定義できます。列挙型を定義することで、定義された値のいずれかが返ってくることが保証されます（それが保証されるように実装しなければなりません）。列挙型がサポートされていない言語でもGraphQLではEnumを定義できます。

```schema.graphql
enum Color {
    RED
    YELLOW
    BLUE
    GREEN
}

type Apple {
    color: Color
}
```

#### リスト
フィールドには型のリストを定義することも可能です。リストは型を角括弧で囲むことで表現できます。以下はStringのリストを持つスキーマの例です。


```schema.graphqls
type Department {
    id: ID!
    memberName: [String]
}
```

#### ルート型
GraphQLのクエリはルート型で始まります。ルート型とは、データソースに対する操作を表現する型です。具体的には以下の通りです。
※わかりやすいようにSQLと比較形式で書いています

|データソースに対する操作|SQL|GraphQL|
|---|---|---|
|データの取得|SELECT|Query|
|データの登録|INSERT|Mutation|
|データの更新|UPDATE|Mutation|
|データの削除|DELETE|Mutation|
|データ更新の監視|-|Subscription|

※GraphQLにはソケット通信を利用してデータの更新を監視するSubscriptionというものも用意されています（SQLでは存在しません）
つまり、Query、Mutation、Subscriptionがルート型になります。

#### ユニオン型（Union型）
ユニオン型は、複数の型のうち一つを返す型です。以下の例では、クエリにagendaを指定するとStudyGroupもしくはWorkoutが返却されます。型はパイプ（|）でつなぎます。

```schema.graphqls
union AgendaItem = StudyGroup | Workout

type StudyGroup {
    name: String!
    subject: String
    students: [User!]
}

type Workout {
    name: String!
    reps: Int!
}

type Query {
    agenda: AgendaItem
}
```

## スキーマの定義の方法
SDLを使って以下のように定義します（定義ファイルの拡張子は、慣例的に.graphqlsとなります）。

#### 基本的な定義
```schema.graphqls
type Book {
    id: ID!
    name: String
    pageCount: Int
    author: Author
}

type Author {
    id: ID!
    firstName: String
    lastName: String
}
```

typeに続けて型名を記述し波括弧で括ります。中身は、「フィールド名: 型名」で表現します（GraphQLの型については別途投稿します）。Bookのフィールドにあるauthorのように、他の型を入れ子にしネスト構造にすることも可能です。

#### エクスクラメーションマーク（!マーク）の意味
上記スキーマ定義のidの型定義に「ID!」のように、エクスクラメーションマーク（!、ビックリマーク）がついています。エクスクラメーションマークがついているフィールドは、そのフィールドがnullになることがないことを意味します。つまり、上記例だと、idフィールはnullになることがなく、それ以外のフィールドはnullの可能性があるということを意味します。

#### リストのエクスクラメーションマーク（!マーク）
リストのエクスクラメーションマークは何パターンか表現方法があります。以下の例では、[String]としていますが、
　[String!]
　[String]!
　[String!]!
といった形でも表現できます。それぞれの意味は以下の通りです。

```schema.graphqls
type Department {
    id: ID!
    memberName: [String]
}
```

|リストの宣言|定義|
|---|---|
|[String]|nullかもしれないリストで中身もnullかもしれない文字列型|
|[String!]|nullかもしれないリストで中身はnullではない文字列型|
|[String]!|nullではないリストで中身はnullかもしれない文字列型|
|[String!]!|nullではないリストで中身もnullではない文字列型|

以上です。

## 参考
* https://www.graphql-java.com/documentation/master/schema/
* https://graphql.org/learn/schema/
* https://www.oreilly.co.jp/books/9784873118932/