Amplify + AppSync(graphQL) + DynamoDB でどんな感じでリソース作られるのか見てみる

だいたいこのあたりのシリーズです。

Amplify + AppSync + Cognitoで読み書きの制御を試してみる
https://qiita.com/ikegam1/items/4868b8a2b473e7ec8f85

## やる事
amplify側で `amplify add api` やら `amplify push`やらするとして、DynamoDB側のGSIとか制御できるのかどうか気になったので試してみる回です。

## 目次

1. 初期設定
2. スキーマ作成
3. DynamoDB確認
4. 参考

## 1. 初期設定

今回は下記が終わっているものとします。

- amplify cilインストール (4.24.3 でした)
- `amplify add auth`によるcognitoの設定
- `npx create-react-app react-amplified` reactかつ *react-amplified* ってプロジェクトフォルダで進める
- プロジェクトフォルダ内での `amplify init`
- 実行環境はWSL2上のubuntu18.4です。

## 2. スキーマ設定

### 2-1. 
amplifyで生成されるBlog exampleをモチーフにしつつ下記のようなスキーマを作成してみます。

```graphql:schema.graphql
type Blog @model
@key (fields: ["id"])
@auth(rules: [
      { allow: owner },
      { allow: private, operations: [read] }
    ])
 {
  id: ID!
  title: String!
  owner: String!
  updated_dt: AWSDateTime!
  created_dt: AWSDateTime!
  TTL: AWSTimestamp!
  posts: [Post] @connection(keyName: "byBlog", fields: ["id"])
}

type Post @model
@auth(rules: [
      { allow: owner },
      { allow: private, operations: [read] }
    ])
@key (fields: ["id"])
@key (
  name: "listByStatus",
  fields: ["status", "updated_dt"],
  queryField: "listPostsByStatus"
)
@key(name: "byBlog", fields: ["blogID"]) {
  id: ID!
  title: String!
  blogID: ID!
  status: String!
  owner: String!
  updated_dt: AWSDateTime!
  created_dt: AWSDateTime!
  TTL: AWSTimestamp!
  blog: Blog @connection(fields: ["blogID"])
}

type Memo @model
@auth(rules: [
      { allow: owner }
    ])
@key (fields: ["owner", "updated_dt"]) {
  id: ID!
  memo: AWSJSON!
  owner: String!
  updated_dt: AWSDateTime!
  created_dt: AWSDateTime!
  TTL: AWSTimestamp!
}
```

- ```@auth```を指定してみた
- ```@key```でPKやSKを指定してみた
- ```@key```でGSIを指定してみた
- AWSDateTimeやAWSJSONというAppSyncで使える型を使ってみた

## 2-2.

次に `amplify add api`します

```
$ amplify add api

? Please select from one of the below mentioned services: GraphQL
? Provide API name: reactamplified
? Choose the default authorization type for the API Amazon Cognito User Pool
Use a Cognito user pool configured as a part of this project.
? Do you want to configure advanced settings for the GraphQL API No, I am done.
? Do you have an annotated GraphQL schema? No
? Do you want a guided schema creation? Yes
? What best describes your project: One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)
? Do you want to edit the schema now? Yes

GraphQL schema compiled successfully.

```

**Do you want to edit the schema now?** のとこで前述のスキーマを記述します。

そして

```
amplify push
```

(そういや、**? Choose the code generation language target** のとこで出てくる`flow`って何だろね？気が向いたら調べる)

pushが完了したら、作成されたリソースを確認してみましょう。
まずはAppSyncのコンソールを

## 3. AppSync コンソール

![appsync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/5f5ef470-ca4b-43f3-700a-8e86f53c93c2.png)

ちゃんとスキーマが反映されてる。なるほど、BlogとPostのリレーショナルはこんな感じになるのか。

で、こんな感じでMutation実行しときます。
AppSyncコンソールのクエリのとこから実行できます。

```
mutation MyMutation {
  createBlog(input: {title: "日記ブログログ", updated_dt: "2020-08-10T11:11:11.111Z", created_dt: "2020-08-10T11:11:11.111Z", TTL: 1572268323, owner: "testUser01"}) {
    id
  }
}

mutation MyMutation {
  createPost(input: {title: "今日のカレー", blogID: "7998ea07-d679-4a6d-bca8-5ce6af692929", status: "ACTIVE", owner: "testUser01", created_dt: "2020-08-10T11:11:11.111Z", TTL: 1572268323, updated_dt: "2020-08-10T11:11:11.111Z"}) {
    id
  }
}

mutation MyMutation {
  createMemo(input: {memo: "{}", owner: "testUser01", updated_dt: "2020-08-10T11:11:11.111Z", created_dt: "2020-08-10T11:11:11.111Z", TTL: 1572268323}) {
    id
  }
}
```

![appsync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/46bd4dfe-0229-2f6e-4579-448a0134eef0.png)


`owner` は明示的に記載しない方がいいのかな。cognito上のユーザー名を入力してみたけどあってるかわからん。
あと`createdAt` とか`updatedAt` も作られてる。これも明示的には作らない方が良さそうだ。

なお、Queryはこんな感じ。

```
query MyQuery {
  listPostsByStatus(filter: {owner: {beginsWith: "Test"}}, status: "ACTIVE", updated_dt: {ge: "2020-08-01"}) {
    nextToken
    items {
      owner
      status
      title
      id
      created_dt
    }
  }
}
```

filterを設定しないとなんか怒られた。


4. DynamoDB側

次にDynamoDBの定義がどんな感じになってるか確認。
ちなみにAppSyncのデータソースのところはこういう感じ。

![appsync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/af89964a-15a2-5335-bf09-e527fd8e9c89.png)


### Postsの項目

![dynamo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/44396797-247b-5d17-77e8-6131d8113cbf.png)


`__typename` っていうのが作られてる。
`creaetdAt` とかにはnowな時間が勝手に入ってくれるんですね。

### PostsのGSI

![dynamo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/a94cd5a5-9fa5-bf1b-f526-861454f04f2e.png)

うん。想定通り。 ```@key``` で指定すれば作られる。

あんまり複雑な事をしないのであればけっこう簡単そうな印象。


## 5. 参考
https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/scalars.html
https://d1.awsstatic.com/ja_JP/startupday/sudo2020/SUD_Online_2020_Tech07.pdf

## これも忘れずに

```
$ amplify delete
```