GraphQLサーバーにクエリを実行する方法

## GraphSQL

## Queries And Mutations

### Arguments
REST API: リクエスト内のクエリパラメータとURLセグメントのみ
GraphQL: オブジェクトが独自の引数を取得できる -> 複数のAPIフェッチを完全に置き換えることができます.

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

```json
{
  "data": {
    "human": {
      "name": "Luke Skywalker",
      "height": 5.6430448
    }
  }
}
```



### Alias
`Arguments`の例だと, 異なる引数を持つフィールドを複数もつことができない

**NG**
```graphql
{
  human(id: "1000") {
    name
    height(unit: FOOT)
  },
  human(id: "1001") {
    name
    height(unit: FOOT)
  }
}
```

GraphQLでは, Aliasを指定して対応可能.

```graphql
{
  human1000: human(id: "1000") {
    name
  }
  human1001: hero(id: "1001") {
    name
  }
}
```

```json
{
  "data": {
    "human1000": {...},
    "human1001": {...}
  }
}
```

### Fragments
**再利用可能なユニット**
重複するフィールドセットはFragmentsに書き出す.

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

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

```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"
        }
      ]
    }
  }
}
```

#### Fragments + variables
```graphql
query HeroComparison($first: Int = 3) {
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  friendsConnection(first: $first) {
    totalCount
    edges {
      node {
        name
      }
    }
  }
}
```

```json
{
  "data": {
    "leftComparison": {
      "name": "Luke Skywalker",
      "friendsConnection": {
        "totalCount": 4,
        "edges": [
          {
            "node": {
              "name": "Han Solo"
            }
          },
          {
            "node": {
              "name": "Leia Organa"
            }
          },
          {
            "node": {
              "name": "C-3PO"
            }
          }
        ]
      }
    },
    "rightComparison": {
      "name": "R2-D2",
      "friendsConnection": {
        "totalCount": 3,
        "edges": [
          {
            "node": {
              "name": "Luke Skywalker"
            }
          },
          {
            "node": {
              "name": "Han Solo"
            }
          },
          {
            "node": {
              "name": "Leia Organa"
            }
          }
        ]
      }
    }
  }
}
```


### Operation name 
特になし
ref: https://graphql.org/learn/queries/#operation-name

### Variables

#### Variable definitions
optional な場合 `!`を付与する

```
query HeroForEpisode($ep: Episode!) {
  hero(episode: $ep) {
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      height
    }
  }
}
```


#### Default variables 
デフォルト値を設定する場合以下のように表現する

```
query HeroNameAndFriends($episode: Episode = JEDI) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}
```

### Directives
Directiveはフィールドまたはフラグメントに添付でき,
サーバーが望む方法でクエリの実行に影響を与える可能性があります

クエリのフィールドを追加および削除するために文字列操作を行う必要がある状況を回避するのに役立ちます

- @include(if: Boolean) trueの場合にのみ、このフィールドを結果に含める
- @skip(if: Boolean) trueの場合、このフィールドをスキップします


### Mutations
RESTではGETでデータを更新することは推奨されていない.
同様にGraphQLでも、クエリを実装してデータを書き込むことは推奨されない。

書き込みを引き起こす操作は、ミューテーションを介して明示的に送信する必要があるという規則を確立すると便利です

```
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}
```

### Inline Fragments
GraghQLは, interfaceとunion typeを持つ.

```
query HeroForEpisode($ep: Episode!) {
  hero(episode: $ep) {
    name
    ... on Droid {
      primaryFunction
    }
    ... on Human {
      height
    }
  }
}
```


### Meta Fields
GraphQLサービスから返されるタイプがわからない状況がある場合、クライアントでそのデータを処理する方法を決定する方法が必要である
クエリの任意の時点でメタフィールドである`__typename`を要求して、その時点でのオブジェクトタイプの名前を取得できる

```
{
  search(text: "an") {
    __typename
    ... on Human {
      name
    }
    ... on Droid {
      name
    }
    ... on Starship {
      name
    }
  }
}
```