Amplifyで自動構築される内容の観察:Schema.graphql編

Amplifyで自動構築される内容の観察:Schema.graphql編

こんにちは!

この記事は Amplify CLI を使って自動構築されたリソースを観察するシリーズです。VTL 編と、DynamoDB 編もありますので、こちらも併せてご覧ください!

想定する読者

  • Amplify が気になっているヒト
  • Amplify CLI を使ってみたいヒト
  • 最近 Amplify CLI を知ったヒト

はじめに

GraphQL を作成するコマンドは対話型のため、以下のように設定しました。

なお「 Amplfiy で自動構築される内容の観察」シリーズすべての記事は、下記の設定を利用しております。

$ amplify add api
? Please select from one of the below mentioned services: GraphQL
? Provide API name: amplifytest
? Choose the default authorization type for the API Amazon Cognito User Pool
 Do you want to use the default authentication and security configuration? Default configuration
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
? Do you want to configure advanced settings for the GraphQL API No, I am done.
? Do you have an annotated GraphQL schema? No
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)
? Do you want to edit the schema now? No
$ amplify push
? Are you sure you want to continue? Yes
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2

※ Amplify CLI のバージョンは 4.44.1になります。

作成されるスキーマを解説

Amplify CLI は型を定義して amplify push コマンドを実行するだけで Query や Mutation を自動生成してくれます。なお型を定義するファイルは、AMPLIFY_PROJECT_NAME/backend/api/API_NAME 配下にある schema.graphql となります。

さっそく自動生成されたスキーマを見ていきましょう。Todo テンプレートを選択した場合は、以下のように定義されています。

type Todo @model {
  id: ID!
  name: String!
  description: String
}

とてもシンプルな定義です。これを amplify push すると以下のようなスキーマが作成されています。AppSync の GUI コンソール画面などで確認してみましょう。

type Mutation {
	createTodo(input: CreateTodoInput!, condition: ModelTodoConditionInput): Todo
	updateTodo(input: UpdateTodoInput!, condition: ModelTodoConditionInput): Todo
	deleteTodo(input: DeleteTodoInput!, condition: ModelTodoConditionInput): Todo
}

type Query {
	getTodo(id: ID!): Todo
	listTodos(filter: ModelTodoFilterInput, limit: Int, nextToken: String): ModelTodoConnection
}

type Subscription {
	onCreateTodo: Todo
		@aws_subscribe(mutations: ["createTodo"])
	onUpdateTodo: Todo
		@aws_subscribe(mutations: ["updateTodo"])
	onDeleteTodo: Todo
		@aws_subscribe(mutations: ["deleteTodo"])
}

type Todo {
	id: ID!
	name: String!
	description: String
	createdAt: AWSDateTime!
	updatedAt: AWSDateTime!
}

すべて記載するとかなり長くなってしますので、一部抜粋しています。それではポイントとなるところをピックアップしてみましょう。

Mutation

Mutation の部分では、create/update/delete の操作を行うクエリが必ず定義されます。それに伴い Input 型なども作成されています。

input CreateTodoInput {
	id: ID
	name: String!
	description: String
}

input DeleteTodoInput {
	id: ID
}

input UpdateTodoInput {
	id: ID!
	name: String
	description: String
}

input ModelTodoConditionInput {
	name: ModelStringInput
	description: ModelStringInput
	and: [ModelTodoConditionInput]
	or: [ModelTodoConditionInput]
	not: ModelTodoConditionInput
}

input ModelStringInput {
	ne: String
	eq: String
	le: String
	lt: String
	ge: String
	gt: String
	contains: String
	notContains: String
	between: [String]
	beginsWith: String
	attributeExists: Boolean
	attributeType: ModelAttributeTypes
	size: ModelSizeInput
}

type Mutation {
	createTodo(input: CreateTodoInput!, condition: ModelTodoConditionInput): Todo
	updateTodo(input: UpdateTodoInput!, condition: ModelTodoConditionInput): Todo
	deleteTodo(input: DeleteTodoInput!, condition: ModelTodoConditionInput): Todo
}

データソースを操作する create/update/delete 関連のスキーマが定義されました。 Input 型に定義されているパラメータは、事前に定義したスキーマが反映されます。delete アクションについては ID のみです。

試しに以下のように Todo 型に変更を加えてみましょう。

ype Todo @model {
  id: ID!
  name: String!
  approver: String! # 変更点
  description: String
}

すると以下のように Input 型のスキーマが変わります。

input CreateTodoInput {
	id: ID
	name: String!
	approver: String!
	description: String
}

input DeleteTodoInput {
	id: ID
}

input UpdateTodoInput {
	id: ID!
	name: String
	approver: String
	description: String
}

input ModelTodoConditionInput {
	name: ModelStringInput
	approver: ModelStringInput
	description: ModelStringInput
	and: [ModelTodoConditionInput]
	or: [ModelTodoConditionInput]
	not: ModelTodoConditionInput
}

ひとつのパラメータを追加することで、ほかのスキーマが変化しました。なお Mutation に関連する上記以外のスキーマは内容が変わっておりませんでした。

まとめると、Mutation 型のスキーマや delete 操作などの基本的な型は固定で、あとのスキーマは定義された型によって変動するようです。

Query

Query の部分では、get/list の操作を行うクエリが必ず定義されます。では定義されたスキーマを見ていきましょう。

input ModelIDInput {
	ne: ID
	eq: ID
	le: ID
	lt: ID
	ge: ID
	gt: ID
	contains: ID
	notContains: ID
	between: [ID]
	beginsWith: ID
	attributeExists: Boolean
	attributeType: ModelAttributeTypes
	size: ModelSizeInput
}

input ModelStringInput {
	ne: String
	eq: String
	le: String
	lt: String
	ge: String
	gt: String
	contains: String
	notContains: String
	between: [String]
	beginsWith: String
	attributeExists: Boolean
	attributeType: ModelAttributeTypes
	size: ModelSizeInput
}

type ModelTodoConnection {
	items: [Todo]
	nextToken: String
}

input ModelTodoFilterInput {
	id: ModelIDInput
	name: ModelStringInput
	description: ModelStringInput
	and: [ModelTodoFilterInput]
	or: [ModelTodoFilterInput]
	not: ModelTodoFilterInput
}

type Query {
	getTodo(id: ID!): Todo
	listTodos(filter: ModelTodoFilterInput, limit: Int, nextToken: String): ModelTodoConnection
}

こちらも Mutation のパターンと似て、ge/list のデータソースを操作するところや一部の Input は基本的にスキーマが固定されています。

また定義した型に合わせて連動するものは Query に関連しているところになりますので、フィルターの部分も変動いたします。

Subscription

最後に Subscription の部分です。

type Subscription {
	onCreateTodo: Todo
		@aws_subscribe(mutations: ["createTodo"])
	onUpdateTodo: Todo
		@aws_subscribe(mutations: ["updateTodo"])
	onDeleteTodo: Todo
		@aws_subscribe(mutations: ["deleteTodo"])
}

こちらは Mutation に合わせて Subscription が作成されるようです。Amplify CLI で生成される Mutation 型は、固定で create/update/delete になりますので、この Subscription の部分も基本的には固定となります。

しかし型を定義するところで利用する @model ディレクティブでフィルターをかけると、Subscription 型の部分が変動します。例えば以下のようなスキーマを amplify push したとしましょう。

type Todo @model {
  id: ID!
  name: String!
  description: String
  comments: [Comment] @connection(name: "TodoComments")
}

type Comment @model(subscriptions: null) {
  id: ID!
  content: String
  todo: Todo @connection(name: "TodoComments")
}

上記の記述で Comment 型のサブスクリプションを生成させないことができます。これは @model ( subscriptions: null ) の部分で命令しています。

実際に AppSync の GUI コンソール画面で確認すると、Comment 型に関連するいくつかのスキーマは作成されていますが、Subscription は作成されていないことを確認できます。Subscription が必要ない場合は、@model ディレクティブに記述をしましょう。

関連記事

まとめ

GraphQL のベストプラクティスに則って、自動生成してくれるのはとても助かりますね。設計の参考にもできるので、ぜひ Amplify CLI でスキーマを自動生成してみてください!

このブログでは、GraphQL や GraphQL のマネージドサービスである AWS AppSync の記事をどんどん公開しておりますので、ご興味のある方はほかの記事もご覧いただければと思います。

AppSync に関する開発は、お気軽にお問い合わせください。