「Introduction to GraphQL」をキャッチアップする

AWS AppSyncを始めるにあたり、まずはGraphQLをキャッチアップする必要があったので記事に起こしてみました。

[graphql.org](https://graphql.org/learn/)のイントロから、GraphQLを始めるための情報をピックアップします。

足りない部分は今後追記予定。

# はじめに

GraphQLとは。

- クエリ言語の言語仕様である
- クエリ言語を実行するサーバー側のランタイムも指す

特定のデータストアに結びつく技術ではない。

# GraphQLをはじめるために

次の要素が必要。

- データフィールドと型の定義
- フィールドに対するデータアクセスの実装

```graphql
type Query {
  me: User
}

type User {
  id: ID
  name: String
}
```

データアクセスの実装は、上記の宣言とデータストアを結びつけるもの。GraphQL仕様とは独立した要素だが、必要。

```javascript
// データアクセスの仮実装
function Query_me(request) {
  return request.auth.user;
}

function User_name(user) {
  return user.getName();
}
```

上記のような宣言（と実装）に対して、クライアントから `me` というデータをクエリしてみる。

クエリの表現は下記のようになる。

```graphql
{
  me {
    name
  }
}
```

対するGraphQLサービスからのレスポンスの一例は、以下のようなjsonとなる。

```json
{
  "me": {
    "name": "Luke Skywalker"
  }
}
```


# Queries and Mutations

http://graphql.github.io/learn/queries/

クエリで「欲しいフィールド」を要求することで、GraphQLランタイムは要求されたデータ **のみ** を返す。クライアントにとって必要なデータだけが返るようになっている。ネストされているデータ構造でも有効。

## Auguments

SQLにおける `where` のようなことができる。以下のクエリでは、 `id: "1000"` が相当する。

```graphql
{
  human(id: "1000") {
    name
    height
  }
}
```

クエリの中で引数を宣言的に記述できるので、パッと見がわかりやすい。

また、 `where` だけでなくちょっとした関数の適用のような芸当も可能。以下の例では、スカラータイプのフィールドである `height` に対して、単位を変換して返すようリクエストを行っている。

```graphql
{
  human(id: "1000") {
    name
    height(unit: FOOT)
  }
}
```


## Aliases

引数のみ異なる複数のフィールドにリクエストをかけたい場合に利用する。
次の例では `episode` の引数を変えた2つの `hero` を取り出しており、それぞれに `empireHero` `jediHero` というエイリアスを張っている。

```graphql
{
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
  }
}
```


## Fragments

要求するデータ構造で多少複雑なものが欲しくなった時に。

Exampleを見ていると、個人的にはCのインライン関数やマクロあたりに近いイメージを持った。fragmentを定義してクエリ中に宣言することで、その場所に展開される。

下記の例では `...comparisionFields` にfragmentsで宣言した構造を展開してリクエストを行う様を確認できる。

```graphql
{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}
```

戻ってくるフィールドは `leftComparison` と `rightComparison` である。で、それぞれの中身は `...comparisionFields` の展開形、つまり `fragment comparisonFields` の宣言内容に準じるものとなる。

```json
{
  "data": {
    "leftComparison": {
      "name": "Luke Skywalker",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "C-3PO"
        },
        {
          "name": "R2-D2"
        }
      ]
    },
    "rightComparison": {
      "name": "R2-D2",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        }
      ]
    }
  }
}
```

## Operation name

読んで字の如くで、意図する「操作」を宣言するためのもの。 `query` と `mutation` `subscription` の3種類ある。

`query` に関しては省略記法も利用可能。ここまでのexampleがまさしくで、これらは暗黙的に `query` を利用している。

```graphql
query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}
```

複数のOperationを含むクエリを記述する場合には必須となる。しかし、「操作」を明示的にクエリに含むことがサーバーサイドでのロギング観点で有用であるため、指定することが推奨される。


## Variables

（追記予定）

## Directives

（追記予定）

# Mutations

（追記予定）

# Inline Fragments

（追記予定）


# 参考

- [graphql.org - Introduction to GraphQL](https://graphql.org/learn/)
- [GraphQL入門 - 使いたくなるGraphQL](https://qiita.com/bananaumai/items/3eb77a67102f53e8a1ad)