AppSyncでGraphQLを触ってみる

## 概要
AppSyncのクイックスタートにそってサンプルスキーマを作成してみたのでメモ。
https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/quickstart-launch-a-sample-schema.html

## GraphQLとは
公式トップの日本語訳
> GraphQLは、APIのクエリ言語であり、既存のデータでこれらのクエリを実行するためのランタイムです。GraphQLは、API内のデータの完全で理解しやすい説明を提供し、クライアントが必要なものだけを正確に要求できるようにし、時間の経過とともにAPIを進化させやすくし、強力な開発者ツールを有効にします。


- 公式：https://graphql.org/
- 参考：https://eh-career.com/engineerhub/entry/2018/12/26/103000

## AppSyncとは
- awsが提供する完全マネージメント型のGraphQL サービスのこと
- 公式ドキュメント：https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/welcome.html


## クイックスタートをやってみる
- https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/quickstart-launch-a-sample-schema.html

上記に沿ってイベントアプリのサンプルスキーマを作成すると、新しくShchemaが定義と、データソースであるDynamodbのテーブルが作成される。以下はShcema定義を一部抜粋したもの。

```GraphQL
type Event {
	id: ID!
	name: String
	where: String
	when: String
	description: String
	# Paginate through all comments belonging to an individual post.
	comments(limit: Int = 10, nextToken: String): CommentConnection
}

type Mutation {
	# Create a single event.
	createEvent(
		name: String!,
		when: String!,
		where: String!,
		description: String!
	): Event
	# Delete a single event by id.
	deleteEvent(id: ID!): Event
	# Comment on an event.
	commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment
}

type Query {
	# Get a single event by id.
	getEvent(id: ID!): Event
	# Paginate through events.
	listEvents(filter: TableEventFilterInput, limit: Int = 10, nextToken: String): EventConnection
}

type Subscription {
	subscribeToEventComments(eventId: String!): Comment
		@aws_subscribe(mutations: ["commentOnEvent"])
}

schema {
	query: Query
	mutation: Mutation
	subscription: Subscription
}
```

### schema
- ルート型と呼ばれるもの

```GraphQL
schema {
	query: Query
	mutation: Mutation
	subscription: Subscription
}
```

### query
- GraphQLにおける、データ取得を行う仕組み。

```GraphQL
type Query {
	# Get a single event by id.
	getEvent(id: ID!): Event
	# Paginate through events.
	listEvents(filter: TableEventFilterInput, limit: Int = 10, nextToken: String): EventConnection
}
```



### mutation
- GraphQLにおける、データを更新する仕組み。登録、更新、削除処理等を行う

```GraphQL
type Mutation {
	# Create a single event.
	createEvent(
		name: String!,
		when: String!,
		where: String!,
		description: String!
	): Event
	# Delete a single event by id.
	deleteEvent(id: ID!): Event
	# Comment on an event.
	commentOnEvent(eventId: ID!, content: String!, createdAt: String!): Comment
}
```
### subscription
参考：https://qiita.com/yoshii0110/items/fbee34d5c235a2a064f9
　　：https://qiita.com/yoshii0110/items/3d9ec03215537646b65c

> Mutationをトリガーにしたイベントベースでの処理が行えます。
Mutationとは、GraphQLにおけるトランザクション処理(Put/Post/Delete)のことを指しています。
なので、クライアント側でPut/Post/DeleteをGraphQLサーバ側に行った場合、このPut/Post/Deleteの処理をサブスクリプションしているクライアントがいた場合、そのクライアントに対し、行われた処理内容のデータをpushすることができます

```GraphQL
type Subscription {
	subscribeToEventComments(eventId: String!): Comment
		@aws_subscribe(mutations: ["commentOnEvent"])
}
```

### datasource
> データソースは、AWS AppSync がユーザーに代わってアクセスできるアカウント内の AWS リソースです

- DynamoDB、RDS（Aurora Serverless）、Elasticsearch、Lambda、HTTPエンドポイント等を指定することが可能

### resolver
> リゾルバーは、GraphQL リクエストをデータソースが理解できる形式に変換する関数です。リゾルバーには、コンテキストオブジェクトにアクセスして、変換および実行ロジックを定義するリクエストおよび応答テンプレートがあります。

- データソース同様に、DynamoDB、RDS（Aurora Serverless）、Elasticsearch、Lambda、HTTPエンドポイント等を指定することが可能
- ドキュメント：https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/resolver-mapping-template-reference.html

- Queryおよび、Mutationにはリゾルバーと呼ばれるものがアタッチされており、リゾルバーを介してデーターソース（今回はDynamodb）からデータの取得や、登録、削除を行うことが可能。AWSコンソール上のResolversから確認ができ、リゾルバーの中身は以下のようになっている。


#### Mutaions: CreateEventに対するリゾルバー

データソース名：AppSyncEventTable

```JSON:リクエストマッピングテンプレート
{
    "version": "2017-02-28",
    "operation": "PutItem",
    "key": {
        "id": { "S": "$util.autoId()"}
    },
    "attributeValues": {
        "name": { "S": "$context.arguments.name" },
        "where": { "S": "$context.arguments.where" },
        "when": { "S": "$context.arguments.when" },
        "description": { "S": "$context.arguments.description" }
    }
}
```

```javascript:レスポンスマッピングテンプレート
$util.toJson($context.result)
```

#### Query:getEventsに対するリゾルバー

データソース名：AppSyncEventTable

```json:リクエストマッピングテンプレート
{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "id": { "S": "$context.arguments.id" }
    }
}
```

```javascript:レスポンスマッピングテンプレート
$util.toJson($context.result)
```


## Mutation、Queryの実行

- https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/quickstart-write-queries.html
- AWSコンソールの「クエリ」から、クエリを実行することが可能。クエリのリクエストおよびレスポンスのフォールドを選択することが可能。

- Mutationの実行
    - 実行すると、DynamoDBへデータが登録される

```
mutation add {
    createEvent(
        name:"My First Event"
        where:"Today"
        when:"My House"
        description:"Very first event"
    ){
        id
        name
        where
        when
        description
    }
}
```

- queryの実行

```Graphql
query get {
    getEvent(id:"XXXXXX-XXXX-XXXXXXX-XXXX-XXXXXXXXX"){
        name
        where
        when
        description
    }
}
```

```json:
{
  "data": {
    "getEvent": {
      "id": "db9ac484-1424-4c07-b470-d7238efad04b",
      "name": "My First Event",
      "when": "Today",
      "where": "My House",
      "description": "Very first event"
    }
  }
}
```

- curl でのquery実行も可能

```
$ curl -X POST -H "Content-Type:application/graphql" -H "x-api-key:[APIキー]" -d '{ "query": "query { getEvent(id: \"[EventTableのID]\") { name } }" }' [APIURL]
```

## あとがき
とりあえず触って見たものの、まだ全体像がつかめていないので、引き続きRESTの詳しい比較や、メリデメ等について調べる。

## その他読みたいもの
- https://note.com/konpyu/n/nc4fd122644a1
- https://circleci.com/ja/blog/introduction-to-graphql/
- https://qiita.com/NagaokaKenichi/items/a4991eee26e2f988c6ec
- https://www.webprofessional.jp/rest-2-0-graphql/
- https://wawoon.dev/posts/tips-of-graphql-schema-design
- https://qiita.com/hitochan777/items/04c16ca770f7b3a84af5
- https://qiita.com/hitochan777/items/450ae5a1ff821a217179
- https://eh-career.com/engineerhub/entry/2018/12/26/103000
- https://bitjourney.kibe.la/shared/entries/1f26acbe-315f-42b8-9ecd-11bcaac5b697