AppAsync

1. 開始方法

下記の方法で、アプリを簡単に作成できます。この場合、DynamoDBのテーブルが自動で生成されます。

  1. ウィザードで作成
  2. モデル名を好きに決める。モデルテーブル設定で作成するDynamoDBのテーブル名やプライマリキーを設定できる。
  3. APIの名前を決める

2. スキーマとリゾルバ―

スキーマ画面では以下のような構成になっています。Schemaではスキーマの定義が書いてあります。右側にはレゾルバーの定義が書いてあります。

schema

以下のようなスキーマがデフォルトで作成されます。

input CreateMyModelTypeInput {
	title: String
}

input DeleteMyModelTypeInput {
	id: ID!
}

type Mutation {
	createMyModelType(input: CreateMyModelTypeInput!): MyModelType
	updateMyModelType(input: UpdateMyModelTypeInput!): MyModelType
	deleteMyModelType(input: DeleteMyModelTypeInput!): MyModelType
}

type MyModelType {
	id: ID!
	title: String
}

type MyModelTypeConnection {
	items: [MyModelType]
	nextToken: String
}

type Query {
	getMyModelType(id: ID!): MyModelType
	listMyModelTypes(filter: TableMyModelTypeFilterInput, limit: Int, nextToken: String): MyModelTypeConnection
}

type Subscription {
	onCreateMyModelType(id: ID, title: String): MyModelType
		@aws_subscribe(mutations: ["createMyModelType"])
	onUpdateMyModelType(id: ID, title: String): MyModelType
		@aws_subscribe(mutations: ["updateMyModelType"])
	onDeleteMyModelType(id: ID, title: String): MyModelType
		@aws_subscribe(mutations: ["deleteMyModelType"])
}

input TableBooleanFilterInput {
	ne: Boolean
	eq: Boolean
}

input TableFloatFilterInput {
	ne: Float
	eq: Float
	le: Float
	lt: Float
	ge: Float
	gt: Float
	contains: Float
	notContains: Float
	between: [Float]
}

input TableIDFilterInput {
	ne: ID
	eq: ID
	le: ID
	lt: ID
	ge: ID
	gt: ID
	contains: ID
	notContains: ID
	between: [ID]
	beginsWith: ID
}

input TableIntFilterInput {
	ne: Int
	eq: Int
	le: Int
	lt: Int
	ge: Int
	gt: Int
	contains: Int
	notContains: Int
	between: [Int]
}

input TableMyModelTypeFilterInput {
	id: TableIDFilterInput
	title: TableStringFilterInput
}

input TableStringFilterInput {
	ne: String
	eq: String
	le: String
	lt: String
	ge: String
	gt: String
	contains: String
	notContains: String
	between: [String]
	beginsWith: String
}

input UpdateMyModelTypeInput {
	id: ID!
	title: String
}

順に内容を見ていきます。

2.1 型

基本的な型としては以下のものがあります。

名前 意味
String 文字列
Int 整数型
Float 整数型
Boolean 論理型
ID ID型

他にもリスト型なら[]で囲めば定義でき、オブジェクト型もtypeにより定義可能です。例えば、以下なら、MyModelTypeというオブジェクト型が定義されています。そして、MyModelTYpeConnectionのitemsでは、MyModelTypのリストが定義されています。

type MyModelType {
	id: ID!
	title: String
}

type MyModelTypeConnection {
	items: [MyModelType]
	nextToken: String
}

ここで出てくる「!」ですが、必ずあるという意味を示します。例えば、MyModelTypeなら必ずidを含みます。

2.2 ルートクエリ型

schemaを使用して、ルートクエリ型を定義できます(AWSコンソール側では表示されないが、schema.graphqlをエクスポートすると記述あり)。

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

上記より、ルートクエリとして、Query、Mutation、Subscriptionがあることが分かります。それぞれ、検索、変更、更新時動作程度に理解しておくといいと思います。順にみていきます。

2.2.1 Query(検索)

Query部分の値を指定すると、その値を取得できます。例えば、以下ならgetMyModelTypeによりMyModelType型の値を得ることができます。また、listMyModelTypesによりMyModelTypeConnectionを得ることができます。

type Query {
	getMyModelType(id: ID!): MyModelType
	listMyModelTypes(filter: TableMyModelTypeFilterInput, limit: Int, nextToken: String): MyModelTypeConnection
}

形式としては「名前(引数): 戻り値」となります。戻り値のオブジェクト型はtype型で定義されており、引数のオブジェクト型はinput形で定義します。例えば、TableMyModelTypeFilterInputは以下のようになり、idとtitleを指定できることがわかります。

input TableMyModelTypeFilterInput {
  id: TableIDFilterInput
  title: TableStringFilterInput
}

getMyModelTypeやlistMyModelTypesの引数と戻り値はわかるけど動作はよくわかりません。動作を定義する部分はResolverと呼ばれる部分で行います。ResolverはSchemaウィンドウの右にあるResolversウィンドウのgetMyModelTypeの右側にリンクがあるのでそれをクリックするとみることができます。リゾルバにはリクエストマッピングテンプレートとレスポンスマッピングテンプレートがあります。リクエストマッピングテンプレートでは以下のようになっています。

{
  "version": "2017-02-28",
  "operation": "GetItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($ctx.args.id),
  },
}

これは、DynamoDBからGetItemで値を取得するリクエストを出すという意味になります。$ctx.argsは、getMyModelTypeの引数を意味します。引数にidしかないので、idを取得できます。$utilは便利な関数が入っています。

レスポンスマッピングテンプレートは以下の通りです。

$util.toJson($context.result)

GetItemした結果をJSON形式で返すという意味になります。以上のことから、getMyModelTypeにより、DynamoDBにGetItem命令により値をとってくるという動作をしていることが分かります。

2.2.2 Mutation(変更)

データベースを更新する際はMutationを使用します。以下のように定義されています。

type Mutation {
  createMyModelType(input: CreateMyModelTypeInput!): MyModelType
  deleteMyModelType(input: DeleteMyModelTypeInput!): MyModelType
  updateMyModelType(input: UpdateMyModelTypeInput!): MyModelType
}

リゾルバ―部分では、DynamoDBでのPutItem、DeleteItem、UpdateItemが使用されています。

2.2.3 Subscription (購読)

SubscriptionではMutationがあったらアプリに伝えることができます。以下のように定義されています。

type Subscription {
  onCreateMyModelType(id: ID, title: String): MyModelType @aws_subscribe(mutations : ["createMyModelType"])
  onDeleteMyModelType(id: ID, title: String): MyModelType @aws_subscribe(mutations : ["deleteMyModelType"])
  onUpdateMyModelType(id: ID, title: String): MyModelType @aws_subscribe(mutations : ["updateMyModelType"])
}

@aws_subscribe部分をつけると、どのmutationが実行されたらトリガーを引くかを指定することができます。どれも更新のあったMyModelTypeが返ってくることが分かります。リゾルバ―はありません。

3. クエリ

定義したスキーマを使用する際にクエリを使用します。クエリはExpolorerで簡単に作成できます。真ん中のウィンドウに定義されたクエリが表示されます。右側は実行後のログが表示されます。

query

3.1 Mutation

下記の命令をするとmutationのcreateMyModelTypeが実行されます。idとtitleを返します。

mutation createMyModelType($createmymodeltypeinput: CreateMyModelTypeInput!) {
  createMyModelType(input: $createmymodeltypeinput) {
    id
    title
  }
}

引数にCreateMyModelTypeInputを指定します。$createmymodeltypeinputに下ウィンドウのクエリ変数で定義したものが入ります。この場合は、「Hello, world!」です。再生ボタンから実行すると、値がデータベースに登録されます。

3.2 Query

初期にlistMyModelTypesというクエリが定義されています。これを実行すると、queryで定義したlistMyModelTypesが実行されます。引数はないので、データベースの値をすべてリストでとってくることになります。itemsに値が格納されます。実行すると先ほど作成した項目が取得されます。

query listMyModelTypes {
  listMyModelTypes {
    items {
      id
      title
    }
  }
}

4. Cognitoとの連携

4.1 設定

設定を選択し、デフォルト認証モードのAPIレベルをAmazon Cognitoユーザープールを指定します。そして、AWSリージョンとユーザープールを選択します。これで保存すると、Cognitoでの認証ができるようになります。

デフォルトのアクションは、初期でのアクセスをどうするかをしています。ALLOWの場合は、Cognitoユーザーなら初期からAPIをすべて使用できます。DENYにすると、「@aws_auth」による制御をスキーマにつけて許可しないとAPIを使用することができません。

4.2 リゾルバーでCognitoの情報を使う

Cognitoのusernameを使ってDynamoDBを操作したいケースは多いと思います。その場合は、「$context.identity」を使用します。例えば以下のように「createMyModelType」を変更すると、DynamoDBにidがusernameで登録されるようになります。

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($context.identity.username),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

ユーザーのクレームを取りたい場合は「$context.identity.claims.get(“email”)」のようにします。email部分はとりたい値に依存して変えてください。

ZIDO Corp. ALL RIGHTS RESERVED.